Search code examples
androidandroid-fragmentsandroid-listviewandroid-viewpagerfragmentstatepageradapter

How to avoid recreate Fragment into ViewPager?


I am using a ViewPager with a FragmentStatePagerAdapter that contains 5 pages.

In the first page I have a ListView with items. When I change at the last page of the ViewPager, and I come back to first page, my ListView is empty because the Adapter has been recreated.

Android always calls to the next methods: onAttach(), onCreate(), onCreateView(), onViewCreated(), onActivityCreated(), onStart() and onResume().

I would like don't use ViewPager.setOffscreenPageLimit() methods to avoid that my pages can be destroyed. There are any alternative solution?

The behavior I want is the same that makes Facebook.

What I doing wrong? How I can keep the data in my ListView?

Code of my FragmentStatePageAdapter:

public class AdapterMain extends FragmentStatePagerAdapter {
    List<ChicfyFragment> fragments = new ArrayList<ChicfyFragment>();

    public AdapterMain(FragmentManager fm) {
        super(fm);

        fragments.add(new FragmentShop());
        fragments.add(new FragmentSearch());
        fragments.add(new FragmentSell());
        fragments.add(new FragmentNotification());
        fragments.add(new FragmentProfile());
    }

    @Override
    public Fragment getItem(int position) {
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }
}

Code of the first page of my ViewPager:

public class FragmentShop extends ChicfyFragment implements SwipeRefreshLayout.OnRefreshListener {

    ListView mListView;
    AdapterProductList mAdapter;
    SwipeRefreshLayout mSwipeRefreshLayout;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_main_shop, container, false);

        mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_refresh);
        mListView = (ListView) view.findViewById(R.id.fragment_main_shop_listview);

        return view;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // setup adapter
        mAdapter = new AdapterProductList((FragmentActivity) getActivity(), new ArrayList());

        // setup listview
        mListView.setAdapter(mAdapter);
        mListView.setDivider(null);

        // setup swipe
        mSwipeRefreshLayout.setColorScheme(R.color.red, R.color.white, R.color.blue, R.color.white);
        mSwipeRefreshLayout.setOnRefreshListener(this);
    }

    @Override
    public void onRefresh() {
        new AsyncTask<Void, Void, Void>() {
            List<String> list = new ArrayList<String>();

            @Override
            protected Void doInBackground(Void... voids) {
                try {
                    Thread.sleep(1000);
                    for(int i=0; i<10; i++) list.add("" + i);
                } catch (Exception e) {}
                return null;
            }

            @Override
            protected void onPostExecute(Void aVoid) {
                super.onPostExecute(aVoid);

                mAdapter.clear();
                mAdapter.addAll(list);
                mAdapter.notifyDataSetChanged();

                mSwipeRefreshLayout.setRefreshing(false);
            }
        }.execute();
    }
}

Solution

  • I have fixed it as follow:

    In the method onViewCreated() of my Fragment, I avoid recreate the Adapter, checking if is null.

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    
        // setup adapter
        if(mAdapter == null) {
            mAdapter = new AdapterProductList((FragmentActivity) getActivity(), new ArrayList());
            mAdapter.setOnLastItemListener(this);
        }
    
        ...
        ...
    
    }