Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fragment lifecylce behaviour using ViewPager2 and FragmentStateAdapter

I am displaying 5 fragments using ViewPager2 and FragmentStateAdapter. Each fragment has ExoPlayer instance. I am maintaining ViewPager2.setOffscreenPageLimit(1) and it is working well for loading fragments. However, when I scroll down the ViewPager2 to pos4, pos2 and pos1 are supposed to call onStop() , onDestroyView(), onDestroy(). But that is not happening.

None of these methods are executing unless I press onBackPress(). Is there anything I am missing with the implementation part of FragmentStateAdapter.

I want to perform exoPlayer.release() on onDestroyView() to free the memory of the application.

Here is the code

Activity

List<Post> postsList = response.getPosts();
ViewPagerAdapter adapter = new ViewPagerAdapter(this, postsList);
binding.pager.setOrientation(ViewPager2.ORIENTATION_VERTICAL);
binding.pager.setOffscreenPageLimit(1);
binding.pager.setAdapter(adapter);

ViewPagerAdapter

public class ViewPagerAdapter extends FragmentStateAdapter {

    private List<Post> postList;

    public ViewPagerAdapter(@NonNull FragmentActivity fragmentActivity, List<Post> postList) {
        super(fragmentActivity);
        this.postList = postList;
    }


    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return new PostFragment(postList.get(position), position);
    }

    @Override
    public int getItemCount() {
        if (postList == null) return 0;
        return postList.size();
    }

}

Updated

This is also a similar question

like image 950
Rajat Sangrame Avatar asked Feb 28 '20 12:02

Rajat Sangrame


2 Answers

I have referred this POST for the solution.

VeiwPager2 is built on RecyclerView component and FragmentStateAdapter replaces FragmentStatePagerAdapter.

Assuming offscreenPageLimit = 1, ViewPager2 will have 3fragments and 2 fragments preloaded/cached by RecylerView Preloading Strategies So, there will be total 5 fragments loaded.

To disable preloading and caching, I performed:

private void disableCacheOfViewPager() {

    try {

      // Disable Preloading
        ((RecyclerView) binding.pager.getChildAt(0)).getLayoutManager().setItemPrefetchEnabled(false);
        // Disable Cache
        ((RecyclerView) binding.pager.getChildAt(0)).setItemViewCacheSize(0);

    } catch (NullPointerException e) {

        Log.i(TAG, "disableCacheOfViewPager: " + e.getMessage());
    }
}

Scroll Logs Before

//1st
onStart: 0
onResume: 0
onStart: 1

//2nd
onStart: 2
onPause: 0
onResume: 1

//3rd
onStart: 3
onPause: 1
onResume: 2

//4th
onStart: 4
onPause: 2
onResume: 3

//5th
onStart: 5
onStop: 0
onDestroyView: 0
onDestroy: 0
onDetach: 0
onPause: 3
onResume: 4

Scroll Logs After

//1st
onStart: 0
onResume: 0
onStart: 1

//2nd
onStart: 2
onPause: 0
onResume: 1

//3rd
onStart: 3
onStop: 0
onDestroyView: 0
onDestroy: 0
onDetach: 0
onPause: 1
onResume: 2
like image 165
Rajat Sangrame Avatar answered Oct 18 '22 16:10

Rajat Sangrame


I have the same issue and it's a bug listed in googles page. I am not sure of the solution, but one approach is to forget using ViewPager2 all together and go back to: ViewPager & FragmentStatePagerAdapter. Seems to work fine in the old implementation.

https://issuetracker.google.com/issues/154541095

like image 34
MobDev Avatar answered Oct 18 '22 18:10

MobDev