Use of nested fragment and common errors
Nested fragments (Nested fragments), fragment is added inside the fragment.
When used, the main need to rely on the host fragment getChildFragmentManager()to obtain Fragmentmanger.
While it looks similar to adding fragment in the activity, there are a few areas that require special attention because of the fragment life cycle and the management recovery model.
This article also includes some of the areas that need to be changed from fragment migration to V4.fragment code.
Nesting fragments
Nested fragments Nested fragments is introduced by Android 4.2 API 17.
Objective: To further enhance dynamic multiplexing.
If you want to use before Android 4.2, you can use the Support Library V4 version, followed by a detailed migration process introduction.
Dynamic addition of nested fragment
Call Getchildfragmentmanager () in the host fragment
That is, it can be used to add fragments to this fragment interior.
Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();
Similarly, for internal fragment, the getparentfragment () method can get the host fragment to fragment.
Getchildfragmentmanager () and Getfragmentmanager ()
getChildFragmentManager()is a method in fragment that returns the manager that manages the current fragment internal sub-fragments.
getFragmentManager()Both in activity and in fragment.
In activity, if you are using the V4 support library, the method should be usedgetSupportFragmentManager(), returning the manager that manages fragments in the activity.
In fragment, also called Getfragmentmanager (), returned is the manager who added himself.
That is, if fragment is in activity, Fragment.getfragmentmanager () Gets the manager who manages fragments in the activity.
If fragment is nested in another fragment, Fragment.getfragmentmanager () gets the Getchildfragmentmanager () of its parent.
The summary is: Getfragmentmanager () is this level of management, Getchildfragmentmanager () is the next level of management .
This is actually a tree-shaped management structure.
Why should I use the support library with the support library? There are two reasons:
- To use fragment before the API Level11.
- To be used before API level 17getChildFragmentManager(), use nested fragment.
Where do I need to change to migrate to the support library?
To migrate fragment to the V4 version, you need to change the following places:
import android.app.Fragment;-> import android.support.v4.app.Fragment;
Activity-> FragmentActivity / AppCompatActivity
activity.getFragmentManager ()-> getSupportFragmentManager ()
Loader, LoaderManager, LoaderCursor also need to be changed to v4 package.
activity.getLoaderManager ()-> getSupportLoaderManager ()
Fragment the Ontrimmemory () method is missing.
It used to be this way.
@Override public void onTrimMemory(int level) { super.onTrimMemory(level);
imageLoader.trimMemory(level);
}
The V4 version needs to be changed to this
@Override public void onLowMemory() { super.onLowMemory();
imageLoader.trimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
}
Nesting fragment using common Error Error scenario 1: Placing nested fragment in the layout
Put nested fragment in the layout InflateException in Binary XML
It seems that the use of nested fragment in addition to usegetChildFragmentManager(), the other seems to be no different than before.
If the nested fragment does not require too much control and occupies a place in a fixed position, you may take it for granted to put it into the XML layout file and write a label.
Running at first glance seems to be nothing wrong, run a bit can also be shown, but do not do so, play more than two more complex you will know.
On the official website, there is this sentence:
Note: You cannot inflate a layout into a fragment when that layout includes a <fragment>.
Nested fragments are only supported when added to a fragment dynamically.
There must be a reason for that. Wow, let me tell you something I know:
If fragment is nested in the layout, inflate to this tag is equivalent to adding it into the fragmentmanager.
If the nested parent fragment the method again because it needs to rebuild the view andonCreateView()inflate again, an exception is thrown:InflateException in Binary XML
Why did you do it before? Non-nested situations, fragment directly add to the activity, if need to re-inflate, must be in the OnCreate (), the activity is re-built, so no problem, Because there is no problem with the same fragment in Fragmentmanager.
To give an example:
In the case of nesting, if there is fragmenta in the Fragmente layout, we need to overlay a fragmentd.
It was usedreplace(), andaddToBackStack().
When D is displayed, E is actually destroyed, then back, rebuilding view, that Fragemente needs to be re-oncreateview
() began to walk the life cycle, went to inflate time and saw the Fragmenta label.
But at this point a is actually still inside the fragmentmanager, so it throws the following exception:
android.view.InflateException: Binary XML file line # XX: Binary XML file line #XX: Error inflating class fragment
The location of the crash is at the time of Parent fragment (Fragmente) inflate.
Print the specific exception stack information to see:
at com.example.ddmeng.helloactivityandfragment.fragment.FragmentE.onCreateView(FragmentE.java:35)
at android.app.Fragment.performCreateView(Fragment.java:2220)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:973)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1148)
at android.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1587)
at android.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:578)
at android.support.v4.app.BaseFragmentActivityEclair.onBackPressedNotHandled(BaseFragmentActivityEclair.java:27)
at android.support.v4.app.FragmentActivity.onBackPressed(FragmentActivity.java:189)
Caused by: java.lang.IllegalArgumentException: Binary XML file line #16: Duplicate id 0x7f0c0059, tag null, or parent id 0xffffffff with another fragment for com.example.ddmeng.helloactivityandfragment.fragment.FragmentA
at android.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2205)
Experimental example code
Solution 1: Add child fragment dynamically
There are various ways to solve the above problems, and the most common practice is to use dynamic additions:
Fragment fragmentA = getChildFragmentManager().findFragmentByTag(NESTED_FRAGMENT_TAG); if (fragmentA == null) {
Log.i(LOG_TAG, "add new FragmentA !!");
fragmentA = new FragmentA();
FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.fragment_container, fragmentA, NESTED_FRAGMENT_TAG).commit();
} else {
Log.i(LOG_TAG, "found existing FragmentA, no need to add it again !!");
}
Solution 2: Remove child fragment before exception
If your child fragment is not to be added to the layout, your program does have a case of rebuilding the parent fragment view.
To avoid the above exception, you can also do this (tricky and not recommended):
public void removeChildFragment(Fragment parentFragment) {
FragmentManager fragmentManager = parentFragment.getChildFragmentManager();
Fragment child = fragmentManager.findFragmentById(R.id.child); if (child != null) {
fragmentManager.beginTransaction()
.remove(child)
.commitAllowingStateLoss();
}
}
It is called before the ParentfragmentonCreateView()method is inflate and the method is done before theonSaveInstanceState()save works.
These two places are where the anomalies occur, as long as the remove before it is good.
Error Scenario 2: Put fragment in a dynamic layout
Put the fragment in a dynamic layout. java.lang.IllegalArgumentException: No view found for id
This error was found because one of the sub-fragment in the project was added to the Recyclerview.
Recyclerview to wait until the loader data is taken and then populate the layout of each block.
Or the process above, start the parent fragment, load data, add sub-fragment, this is no problem.
But once the above adds andreplace()addToBackStack()returns again, an exception occurs.
Because when the view is rebuilt, Fragmentmanager holds the child fragment, but cannot find its container, and throws an exception.
I also did a little experiment in my demo program:
Helloactivityandfragment
Nested Fragment in Dynamic Container:
In fragment F, add a framelayout first, and then add the child fragment A.
Then in the activity, with D replace F, press the back key to return, there will be crash:
java.lang.IllegalArgumentException: No view found for id 0x7f0c0062 (com.example.ddmeng.helloactivityandfragment:id/frame_container) for fragment FragmentA{b37763 #0 id=0x7f0c0062 FragmentA}
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:965)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1148)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1130)
at android.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1953)
at android.app.Fragment.performActivityCreated(Fragment.java:2234)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:992)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1148)
at android.app.BackStackRecord.popFromBackStack(BackStackRecord.java:1670)
at android.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1587)
at android.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:578)
at android.app.Activity.onBackPressed(Activity.java:2503)
This is because Fragmentmanager cannot find the corresponding container when returning.
Therefore, you should avoid this practice and try to add fragment to the parent's root layout instead of a dynamically added layout.
Other
With regard to nesting fragments, it is possible to use more cases in conjunction with Viewpager.
This feeling is a long story, think there is a lot of system help to do things, another time to talk about it sometime.
Here is a big brother wrote a tool class fragmentation.
He also has a few blog post analysis of the Pit and the reason (see above repo of the Readme given the link), there are some back stack problems, there are animations and so on, we are interested to see.
Resources
guide:nested fragments
Related Demo
Address of this article:
Android fragment use (ii) nesting fragments (Nested fragments) and common errors
Classification:AndroidLabel:Android, Fragment, Nested fragments
Android fragment use (ii) nesting fragments (Nested fragments) and common errors