setUserVisibleHint вызывается перед onCreateView в fragmentе

Я работаю над ViewPager и использую Fragment там я нашел

setUserVisibleHint (), вызываемый до onCreateView () в fragmentе

Я использую Fragment из библиотеки поддержки android.support.v4.app.Fragment

Это проблема с библиотекой?

Как я могу избавиться от него?

РЕДАКТИРОВАТЬ

Я переопределяю setUserVisibleHint () и не вызываю супер, чтобы избавиться от него.

 @Override public void setUserVisibleHint(boolean isVisibleToUser) { //FIXED: setUserVisibleHint() called before onCreateView() in Fragment causes NullPointerException //super.setUserVisibleHint(isVisibleToUser); } 

 // create boolean for fetching data private boolean isViewShown = false; @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (getView() != null) { isViewShown = true; // fetchdata() contains logic to show data when page is selected mostly asynctask to fill the data fetchData(); } else { isViewShown = false; } } 

Используйте переменную экземпляра isViewShown чтобы решить, следует ли извлекать данные в onCreateView() или в setUserVisibleHint() .

Ниже код содержит логику для onCreateView() :

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.main_layout, container, false); // view initialization steps....... if (!isViewShown) { fetchData(); } // do other stuff } 

Этот код решит вашу проблему. Поскольку он решил мою проблему. 🙂

Этот трюк будет извлекать данные в onCreateView() для прямого onCreateView() с одной страницы на другую, тогда как при прокрутке представления он будет извлекать данные из setUserVisibleHint() . 🙂

вы можете использовать эту логику, также вы можете отключить viewDidAppear любое время, установив isVisible = false

 public class MyFragment extends Fragment { private Boolean isStarted = false; private Boolean isVisible = false; @Override public void onStart() { super.onStart(); isStarted = true; if (isVisible && isStarted){ viewDidAppear(); } } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); isVisible = isVisibleToUser; if (isStarted && isVisible) { viewDidAppear(); } } public void viewDidAppear() { // your logic } } 

Я нашел лучшее решение

 private boolean isVisible; private boolean isStarted; @Override public void onStart() { super.onStart(); isStarted = true; if (isVisible) sendRequest(); //your request method } @Override public void onStop() { super.onStop(); isStarted = false; } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); isVisible = isVisibleToUser; if (isVisible && isStarted) sendRequest(); //your request method } 

Это улучшенная версия ответа fared namrouti . Я тестировал это на многих условиях. Это безопасно.

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment, container, false); if (getUserVisibleHint()) { sendRequest(); } return view; } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser) { if (isResumed()){ sendRequest(); } } } 

Ниже работал для меня ….

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //// create class member variable to store view viewFrag =inflater.inflate(R.layout.fragment_main_favorite, container, false); // Inflate the layout for this fragment return viewFrag; } 

и использовать это

  @Override public void setUserVisibleHint(boolean visible) { super.setUserVisibleHint(visible); if (visible) { View v = viewFrag ; if (v == null) { Toast.makeText(getActivity(), "ERROR ", Toast.LENGTH_LONG ).show(); return; } } } 

Мой SightFragment.java здесь должен сбросить флаги в onDestroyView() :

 package cc.cubone.turbo.core.app; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.View; /** * Fragment for handling view after it has been created and visible to user for the first time. * * 

Specially in {@link android.support.v4.view.ViewPager}, the page will be created beforehand * but not be visible to user. * *

Call {@link android.support.v4.view.ViewPager#setOffscreenPageLimit(int)} to set the number of * pages that should be retained. * * Reference: *

*/ public class SightFragment extends Fragment { private boolean mUserSeen = false; private boolean mViewCreated = false; public SightFragment() { } /*public boolean isUserSeen() { return mUserSeen; } public boolean isViewCreated() { return mViewCreated; }*/ @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (!mUserSeen && isVisibleToUser) { mUserSeen = true; onUserFirstSight(); tryViewCreatedFirstSight(); } onUserVisibleChanged(isVisibleToUser); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { // Override this if you want to get savedInstanceState. mViewCreated = true; tryViewCreatedFirstSight(); } @Override public void onDestroyView() { super.onDestroyView(); mViewCreated = false; mUserSeen = false; } private void tryViewCreatedFirstSight() { if (mUserSeen && mViewCreated) { onViewCreatedFirstSight(getView()); } } /** * Called when the new created view is visible to user for the first time. */ protected void onViewCreatedFirstSight(View view) { // handling here } /** * Called when the fragment's UI is visible to user for the first time. * *

However, the view may not be created currently if in {@link android.support.v4.view.ViewPager}. */ protected void onUserFirstSight() { } /** * Called when the visible state to user has been changed. */ protected void onUserVisibleChanged(boolean visible) { } }

 public class MyFragment extends Fragment { private boolean manageVisibility; public MyFragment() { // Required empty public constructor } public static CommunityFragment newInstance() { Bundle args = new Bundle(); CommunityFragment fragment = new CommunityFragment(); fragment.setArguments(args); return fragment; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment manageVisibility = true; return inflater.inflate(R.layout.fragment_community, container, false); } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (manageVisibility && isVisibleToUser) { // fragment is visible } } else if (manageVisibility) { // fragment is invisible } } } } 

НИЖЕ РАБОТАЕМ ДЛЯ МЕНЯ

Создайте глобальное представление, подобное этому

 private View view; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //Inflate view layout view =inflater.inflate(R.layout.your_fragment, container, false); // return view return view; } 

и использовать это

 @Override public void setUserVisibleHint(boolean isUserVisible) { super.setUserVisibleHint(isUserVisible); //When fragment is visible to user and view is not null then enter here. if (isUserVisible && view != null) { // do your stuff here. } } 

Хотя большинство этих решений работает, вам даже не нужно отслеживать состояние самостоятельно.

С текущими версиями для библиотеки поддержки существует метод isResumed() который, вероятно, может сделать большинство из вас, используя флаг isStarted :

Верните true, если fragment находится в состоянии возобновления. Это верно для продолжительности onResume () и onPause ().

И тогда это так же просто:

  @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isResumed()) { updateUi(isVisibleToUser); } } 

Это лучшее решение, которое я нашел.

  @Override public void onCreateView() { super.onStart(); if (getUserVisibilityHint()){ //do stuff } } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isResumed() && isVisibleToUser) { //do stuff } } 

Создайте этот код в своем setUserVisibleHint () :

 if(isVisibleToUser && getView() != null){ isActive = true; init(); }else if(isVisibleToUser && getView() == null){ isActive = false; }else{ isActive = true; } 

В вашем onCreateView () :

 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { if(!isActive){ init(); } } 
Interesting Posts
Давайте будем гением компьютера.