SetUserVisibleHint called before onCreateView in fragment

I am working on a ViewPager and using Fragment , there I found

setUserVisibleHint () called before onCreateView () in the fragment

I am using Fragment from android.support.v4.app.Fragment support library

Is this a problem with the library?

How can I get rid of it?

EDIT

I override setUserVisibleHint () and do not call super to get rid of it.

 @Override public void setUserVisibleHint(boolean isVisibleToUser) { //FIXED: setUserVisibleHint() called before onCreateView() in Fragment causes NullPointerException //super.setUserVisibleHint(isVisibleToUser); } 
+56
android callback android-fragments
Jun 11 '14 at
source share
12 answers
 // 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; } } 

Use the isViewShown instance variable to decide whether to retrieve data in onCreateView() or in setUserVisibleHint() .

The code below contains the logic for 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 } 

This code will solve your problem. Since he solved my problem. :)

This trick will retrieve data in onCreateView() to directly jump from one page to another, while when scrolling through the view, it will retrieve data from setUserVisibleHint() . :)

+88
Jul 24 '14 at 13:02
source share

you can use this logic, also you can disable viewDidAppear at any time by setting 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 } } 
+30
Aug 26 '15 at 9:52
source share

I found a better solution

 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 } 

This is an improved version of the missing Nambuuti answer. I tested this on many conditions. It's safe.

+13
Jul 01 '17 at 5:46 on
source share
 @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(); } } } 
+4
Nov 07 '16 at 15:34
source share

Below worked for me ....

 @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; } 

and use this

  @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; } } } 
+3
Jan 17 '16 at 12:34
source share

My SightFragment.java here should reset the flags in 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. * * <p>Specially in {@link android.support.v4.view.ViewPager}, the page will be created beforehand * but not be visible to user. * * <p>Call {@link android.support.v4.view.ViewPager#setOffscreenPageLimit(int)} to set the number of * pages that should be retained. * * Reference: * <ul> * <li><a href="http://stackoverflow.com/questions/10024739/how-to-determine-when-fragment-becomes-visible-in-viewpager"> * How to determine when Fragment becomes visible in ViewPager</a> * </ul> */ 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 UI is visible to user for the first time. * * <p>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) { } } 
+1
Dec 29 '15 at 14:56
source share

Although most of these solutions work, you don’t even need to track the status yourself.

Current versions of the support library have an isResumed() method that probably does what most of you are trying to achieve using the isStarted flag:

Return true if the fragment is in a resumed state. This is true for the duration of onResume () and onPause ().

And then it is as simple as:

  @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isResumed()) { updateUi(isVisibleToUser); } } 
+1
Aug 29 '18 at 11:28
source share

BELOW WORKED FOR ME

Please create a global view like this

 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; } 

and use it

 @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. } } 
0
Mar 13 '17 at 17:46 on
source share
 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 } } } } 
0
Aug 24 '17 at 11:53 on
source share

This is the best solution I have found.

  @Override public void onCreateView() { super.onStart(); if (getUserVisibilityHint()){ //do stuff } } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isResumed() && isVisibleToUser) { //do stuff } } 
0
Dec 07 '17 at 15:14
source share

This simple option works in my code:

 @Override public void onStart() { super.onStart(); if (getUserVisibleHint()) { updateUI(); // your logic } } 

as well as

 @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isResumed() && isVisibleToUser) { updateUI(); // your logic } } 
0
May 14, '19 at 15:28
source share

Create this code in setUserVisibleHint () :

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

In onCreateView () :

 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { if(!isActive){ init(); } } 
-one
Jun 20 '17 at 2:55 on
source share



All Articles