Code Xiaosheng, a technology platform focused on the Android field

Join my Android technology group

Author: DDDong, links: https://www.jianshu.com/p/c8e8a0249911 disclaimer: this article has been published, it has been approved DDDong, forwarding etc. Please contact the author

Problem analysis

I have been reading other people’s technical posts in Jane’s book, today I will also write some of my own experience! A recent summary of writing a project that used a lot of fragments!

I think those of you who are new to Android might write:

FragmentManager fragmentManager=getSupportFragmentManager(); FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction(); fragmentTransaction.add(ViewId,fragment); / / or fragmentTransaction. Replace (ViewId, fragments); fragmentTransaction.commit();Copy the code

More basic students will use the show and hide methods

FragmentManager fm = getSupportFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); ft.hide(new FirstFragment()) .show(new SecondFragment()) .commit();Copy the code

It’s true that you can switch between two types of fragments, but if you have a lot of users clicking back and forth, or if you have a lot of fragments, do this every time, and soon your app will get OOM, even if it doesn’t crash. so why?

The following lifecycle occurs when we replace:

image

Think about replacing every time!! How wonderful the world would be!! So what’s the problem? If you look back at the code, you’ll see that a new instance is created every time you add/replace or show/hide, which is why !!!!! is the killer

Without further ado, let me show you my method (extracted) :

/** * add Fragment * @param Manager Fragment manager * @param aClass getClass * @param containerId Id of the Fragment object * Null */protected void addFragment(FragmentManager Manager, Class<? extends BaseFragment> aClass, int containerId, Bundle args) { String tag = aClass.getName(); Logger.d("%s add fragment %s", TAG, aClass.getSimpleName()); Fragment fragment = manager.findFragmentByTag(tag); FragmentTransaction transaction = manager.beginTransaction(); // Open a transaction if (fragment == null) {// Do not add try {fragment = aclass.newinstance (); BaseFragment BaseFragment = (BaseFragment) fragment; // Set base fragment to enter, exit, pop in, Popup animation, setCustomAnimations (baseFragment. Enter (), baseFragment. The exit (), baseFragment. PopEnter (), baseFragment.popExit()); transaction.add(containerId, fragment, tag); If (baseFragment isNeedToAddBackStack ()) {/ / determine whether need to add back stack, addToBackStack (tag); }} catch (Exception e) {e.printStackTrace(); } } else { if (fragment.isAdded()) { if (fragment.isHidden()) { transaction.show(fragment); } } else { transaction.add(containerId, fragment, tag); } } if (fragment ! = null) { fragment.setArguments(args); hideBeforeFragment(manager, transaction, fragment); transaction.commit(); }}/** * all fragments except the currentFragment are hidden ** @param manager * @param transaction * @param currentFragment */private void  hideBeforeFragment(FragmentManager manager, FragmentTransaction transaction, Fragment currentFragment) { List<Fragment> fragments = manager.getFragments(); for (Fragment fragment : fragments) { if (fragment ! = currentFragment && ! fragment.isHidden()) { transaction.hide(fragment); }}}Copy the code

A little explanation:

Check whether the Fragment has been added to the fragmentManager’s activitiy first by going through an ArrayList of mAdded, If you can’t find it, look it up in a map of SparseArray called mActive.

Note:

  1. After a fragment is removed, it is removed only from the mAdded, not from the mActive. The fragment is removed only from the mActive if the transaction in which it was removed is removed from the rollback stack

  2. When we add a fragment, our fragment is added to mAdded, not to mActive.

  3. Only when transaction is added to the rollback stack will our fragment be added to the mActive. So fragments that we find with the findFragmentByTag method are not necessarily added to our activity.

Use:

More code, but I personally feel that it is more convenient to use, and the function is more perfect, use only need two lines of code:

HomeFragment1 homeFragment = new HomeFragment1(); addFragment(getSupportFragmentManager(),homeFragment.getClass(),R.id.main_body,null);Copy the code

When we need to pass values, we simply fill in the prepared bundle as parameters. I’ve also added a pushback judgment to fulfill some of the requirements for pushback. To do this, you need to define a method in the BaseFragment:

protected boolean isNeedToAddBackStack() { return true; }Copy the code

That’s all. If you see any problems or better methods, please comment below.

Fragment module encapsulation skillfully use Fragment, decouple Android6.0 permission adaptation notes

Not afraid of giants

Fear of giants and step on the shoulders of giants

It’s hard to beat that