I have bottom navigation bar on click of item in navigation bar i am replacing fragments. I have 3 fragments A,B,C so on click of b item B fragment is loaded and in B i am calling 3-4 APIs. So now if i go to C and then again come to B a new instance of B Fragment is created and again those APIs are called how can i save the fragment instance state and not call APIs again while changing fragments. This is my code.
mBottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { int id = item.getItemId(); Fragment currentLoaded = fgMan.findFragmentById(R.id.container_body); switch (id) { case R.id.nearby_fragment: if (!(currentLoaded instanceof SpotFeedMapFragment)) { removeScroll(); mNearByFragment = fgMan.findFragmentByTag(NEARBY_FRAGMENT_TAG) != null ? fgMan.findFragmentByTag(NEARBY_FRAGMENT_TAG) : mNearByFragment; fgMan.beginTransaction().setCustomAnimations(R.anim.abc_fade_in, R.anim.abc_fade_out); fgMan.beginTransaction().replace(R.id.container_body, mNearByFragment, NEARBY_FRAGMENT_TAG).commit(); fgMan.executePendingTransactions(); getSupportActionBar().setTitle(getString(R.string.nearby_fragment)); } break; case R.id.route_fragment: if (!(currentLoaded instanceof BusLocationsFragment)) { if (!inParent) { mRl.removeView(fixLayout); p.addRule(RelativeLayout.BELOW, toolbar.getId()); scrollView.setLayoutParams(p); scrollView.addView(fixLayout); mRl.addView(scrollView); inParent = true; } //mFragment = new BusLocationsFragment(); mBusLocFragment = fgMan.findFragmentByTag(BUS_LOC_FRAGMENT_TAG) != null ? fgMan.findFragmentByTag(BUS_LOC_FRAGMENT_TAG) : mBusLocFragment; fgMan.beginTransaction().setCustomAnimations(R.anim.abc_fade_in, R.anim.abc_fade_out); fgMan.beginTransaction().replace(R.id.container_body, mBusLocFragment, BUS_LOC_FRAGMENT_TAG).commit(); fgMan.executePendingTransactions(); getSupportActionBar().setTitle(getString(R.string.app_name)); } break; case R.id.newsfeed_activity: if (!(currentLoaded instanceof NewsFeedActivity)) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) { removeScroll(); } mNewsFeedFragment = fgMan.findFragmentByTag(NEWSFEED_FRAGMENT_TAG) != null ? fgMan.findFragmentByTag(NEWSFEED_FRAGMENT_TAG) : mNewsFeedFragment; fgMan.beginTransaction().setCustomAnimations(R.anim.abc_fade_in, R.anim.abc_fade_out); fgMan.beginTransaction().replace(R.id.container_body, mNewsFeedFragment, NEWSFEED_FRAGMENT_TAG).commit(); fgMan.executePendingTransactions(); getSupportActionBar().setTitle(getString(R.string.news)); } break; } return true; } });
I have already initialized fragments member variables above in onCreate
of MainActivity
You should use a FragmentPagerAdapter to initiate the fragments so when you want to switch in between them, the state of the fragments will be saved.
CutomViewPager viewPager = (CustomViewPager) findViewById(R.id.viewpager1); ViewPagerAdapter adapter = new ViewPagerAdapter (MainActivity.this.getSupportFragmentManager()); adapter.addFragment(new SpotFeedMapFragment(), "title"); adapter.addFragment(new BusLocationsFragment(), "title"); adapter.addFragment(new NewsFeedActivity(), "title"); viewPager.setAdapter(adapter);
then in the bottom navigation selected you can set fragment by simple command
viewPager.setCurrentItem(n);
my viewpager class is as follows:
public class CustomViewPager extends ViewPager { private boolean isPagingEnabled; public CustomViewPager(Context context) { super(context); this.isPagingEnabled = true; } public CustomViewPager(Context context, AttributeSet attrs) { super(context, attrs); this.isPagingEnabled = true; } @Override public boolean onTouchEvent(MotionEvent event) { return this.isPagingEnabled && super.onTouchEvent(event); } //for samsung phones to prevent tab switching keys to show on keyboard @Override public boolean executeKeyEvent(KeyEvent event) { return isPagingEnabled && super.executeKeyEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { return this.isPagingEnabled && super.onInterceptTouchEvent(event); } public void setPagingEnabled(boolean enabled) { this.isPagingEnabled = enabled; } }
in the xml instead of a empty layout for fragemnt u need:
<com.package.util.CustomViewPager android:id="@+id/viewpager1" android:layout_width="match_parent" android:layout_height="match_parent" />
Code for custom FragmentPagerAdapter:
private class ViewPagerAdapter extends FragmentPagerAdapter { private final SparseArray<WeakReference<Fragment>> instantiatedFragments = new SparseArray<>(); private final List<Fragment> mFragmentList = new ArrayList<>(); private final List<String> mFragmentTitleList = new ArrayList<>(); ViewPagerAdapter(FragmentManager manager) { super(manager); } @Override public Fragment getItem(int position) { return mFragmentList.get(position); } @Override public int getCount() { return mFragmentList.size(); } void addFragment(Fragment fragment, String title) { mFragmentList.add(fragment); mFragmentTitleList.add(title); } @Override public Object instantiateItem(ViewGroup container, int position) { final Fragment fragment = (Fragment) super.instantiateItem(container, position); instantiatedFragments.put(position, new WeakReference<>(fragment)); return fragment; } @Override public void destroyItem(ViewGroup container, int position, Object object) { instantiatedFragments.remove(position); super.destroyItem(container, position, object); } @Nullable Fragment getFragment(final int position) { final WeakReference<Fragment> wr = instantiatedFragments.get(position); if (wr != null) { return wr.get(); } else { return null; } } @Override public CharSequence getPageTitle(int position) { return mFragmentTitleList.get(position); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With