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:
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:
-
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
-
When we add a fragment, our fragment is added to mAdded, not to mActive.
-
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