Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setUserVisibleHint called before onCreateView in Fragment

I am working on ViewPager and using Fragment there I found

setUserVisibleHint() called before onCreateView() in Fragment

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

Is this is a problem with Library ?

How can I get rid of it ?

EDIT

I Override setUserVisibleHint() and not calling super to get rid of it.

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    //FIXED: setUserVisibleHint() called before onCreateView() in Fragment causes NullPointerException
    //super.setUserVisibleHint(isVisibleToUser);
}
like image 840
Amit Yadav Avatar asked Jun 11 '14 10:06

Amit Yadav


People also ask

What is called after onCreateView?

The onActivityCreated() method is called after onCreateView() and before onViewStateRestored() . onDestroyView() : Called when the View previously created by onCreateView() has been detached from the Fragment . This call can occur if the host Activity has stopped, or the Activity has removed the Fragment .

How do you use setUserVisibleHint?

After AndroidX setUserVisibleHint is deprecated as a replacement we can use the setMenuVisibility Method. Show activity on this post. Use BottomSheetBehavior https://developer.android.com/reference/android/support/design/widget/BottomSheetBehavior for this type of implementation.

Does fragment have onCreate?

onCreate(Bundle) called to do initial creation of the fragment. onCreateView(LayoutInflater, ViewGroup, Bundle) creates and returns the view hierarchy associated with the fragment. onActivityCreated(Bundle) tells the fragment that its activity has completed its own Activity.

How do you know when a fragment becomes visible?

fragment:fragment:1.1. 0 you can just use onPause() and onResume() to determine which fragment is currently visible for the user. onResume() is called when the fragment became visible and onPause when it stops to be visible. To enable this behavior in the first ViewPager you have to pass FragmentPagerAdapter.


3 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 isViewShown instance variable to decide whether to fetch data in onCreateView() or in setUserVisibleHint().

Below code contains 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. As It solved my problem. :)

This trick will fetch data in onCreateView() for direct jumping from one page to another, whereas when you swipe the view it will fetch the data from setUserVisibleHint() method. :)

like image 60
vikoo Avatar answered Oct 17 '22 20:10

vikoo


you can use this logic, also you can turn off viewDidAppear 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
    }
}
like image 33
Fareed Alnamrouti Avatar answered Oct 17 '22 22:10

Fareed Alnamrouti


I found the best 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
}

It's improved version of fareed namrouti's answer. I tested this on many conditions. It's safe.

like image 15
DrMorteza Avatar answered Oct 17 '22 20:10

DrMorteza