Search code examples
androidandroid-fragmentsandroid-viewpagernavigation-drawerandroid-loadermanager

Drawer NavigationView + Fragments with viewpager, how to avoid caching data when switching fragments in navigation drawer from one to another?


I have a drawer navigationview on the left connects to different fragments with different viewpagers. The structure is as followed.

MainActivity Drawer NavigationView

| Fragment A  -- ViewPagerA ----Tab1 - Fragment1
                                Tab2 - Fragment2
|                               Tab3 - Fragment3

| Fragment B -- ViewPagerB ----Tab1 - Fragment4
                               Tab2 - Fragment5
|                              Tab3 - Fragment6

Fragment1-6 are list view fragments.

The problem is when I switch from Fragment A to Fragment B, viewpager will cache the content of list view from Fragment1 and try to show the cached content to the adapter of Fragment4. So that it always shows wrong information when the first time I switch fragments from navigation drawer.

My Code:

MainActivity:

    public class MainActivity extends Activity {
  @InjectView(R.id.navigation_view) public NavigationView mNavigationView;
    @InjectView(R.id.drawerLayout) public DrawerLayout mDrawerLayout;
//......Layout injections..............///
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

  mDrawerToggle = new ActionBarDrawerToggle(this,mDrawerLayout, mToolbar,R.string.app_name,
                R.string.app_name){

             /** Called when a drawer has settled in a completely closed state. */
             public void onDrawerClosed(View view) {


super.onDrawerClosed(view);
         }

         /** Called when a drawer has settled in a completely open state. */
         public void onDrawerOpened(View drawerView) {
             super.onDrawerOpened(drawerView);
         }
     };

}


  public void setUpToggle()
    {


        mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {

            // This method will trigger on item Click of navigation menu
            @Override
            public boolean onNavigationItemSelected(MenuItem menuItem) {


                if (menuItem.isChecked()) menuItem.setChecked(false);
                else menuItem.setChecked(true);

                //Closing drawer on item click
                mDrawerLayout.closeDrawers();

            switch (menuItem.getItemId()) {



                    case R.id.a_drawer:
                        startFragment(FragmentA.newInstance());
                        return true;

                   case R.id.b_drawer:
                        startFragment(FragmentB.newInstance());
                        return true;



     default:
   Toast.makeText(getApplicationContext(),"More things need to be added",Toast.LENGTH_SHORT).show();
                            return true;

                }
            }
        });


        mDrawerLayout.setDrawerListener(mDrawerToggle);


            mDrawerToggle.syncState();
}
}

Fragment A/B (Exactly the same structures and layouts)

public class TabFragment extends Fragment {

public static TabLayout tabLayout;
public static ViewPager viewPager;
public static int int_items = n; //n is any positive integer
private Context mContext;


@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    /**
     *Inflate tab_layout and setup Views.
     */

    View tabView =  inflater.inflate(R.layout.fragment_tab,null);
    tabLayout = (TabLayout) tabView.findViewById(R.id.tabs);
    viewPager = (ViewPager) tabView.findViewById(R.id.viewpager);

    viewPager.setAdapter(new MyAdapter(getChildFragmentManager()));



    tabLayout.post(new Runnable() {
        @Override
        public void run() {
            tabLayout.setupWithViewPager(viewPager);

        }
    });
    return tabView;

}



class MyAdapter extends FragmentStatePagerAdapter{

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


    }


    @Override
    public Fragment getItem(int position)
    {
        switch (position){
            case 0 : return  new Fragment1();//or Fragment4 5 6 here
            case 1 : return new  Fragment2();
            case 2 : return new  Fragment3();

            default:return new Fragment1();

        }
    }

    @Override
    public int getCount() {

        return int_items;

    }



    @Override
    public CharSequence getPageTitle(int position) {

        switch (position){
            case 0 :
                return "F1";
            case 1 :
                return  "F2";
            case 2 :
                return "F3";

        }
        return null;
    }
}

Fragment 1 - 6 :

public class TabFocusFragmentextends extends Fragment
implements LoaderManager.LoaderCallbacks<Cursor>


{


private TabFocusAdapter mAdapter;
private List<E> mList;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    loadData();// never been executed,:(
    setHasOptionsMenu(true);
}

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

    loadData();
    setupRecyclerView();
    return view;
}

@Override
public void onResume() {
    super.onResume();
}



    @Override
    public void onLoadMore() {
if(NeedLoad)
       loadData();
    }

    private void loadData() {
        //RequestData
    ……
}


private void setupRecyclerView() {
  …...

}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    return new CursorLoader(mActivity, ContentProvider.createUri(E.class, null),
            null, null, null, null);
}

@Override //fragment starts here, why??
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {


    if (loadedList.size() > 0) {
     //crashes here …...

    if (!fullPacketLoaded) {
    }
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {

}

If new fragment list adapter doesn't have an appropriate to show previous content, it will crash.

Based on this question, if you have a better solution for the question down below as well? Why is Tablayout and Viewpager crashing with NullpointerException when I start a fragment with LoaderManager from TabFragment?


Solution

  • Finally fixed.

    In my onCreate() method of which fragment implemented LoaderManager, I did this

      getLoaderManager().initLoader(0, null, this);
            if(!getLoaderManager().getLoader(0).isReset()) {
                getLoaderManager().restartLoader(0, null, this);
            }
    

    It works when new loader was not actived properly.