简体   繁体   中英

androidx.navigation:navigation-fragment:2.2.0, get "You must call removeView() on the child's parent first." on navController.popBackStack()

I like use data binding and navigation graph. But after update androidx dependencies from androidx.navigation:navigation-fragment:2.0.0 on 2.2.0 application is crashed after press button "Back". Crash always after return from other fragment to previous fragment containing FragmentPagerAdapter.

in build.gradle

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

//    This is work
//    implementation 'androidx.appcompat:appcompat:1.0.2'
//    implementation 'androidx.navigation:navigation-fragment:2.0.0'

//  This generate error after backstack
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.navigation:navigation-fragment:2.2.0'
}

For see a problem and getting error, please download example from https://github.com/ABRadzh/ErrorNavigation . Otherwise it will be difficult for me to explain where the error occurs.

  1. Press on any button on any page.
  2. Press hardware "Back" button.
  3. Get error message:
2020-02-11 16:15:13.119 2429-2429/in.pagerview.navigation.databinding.onbackstack E/AndroidRuntime: FATAL EXCEPTION: main
    Process: in.pagerview.navigation.databinding.onbackstack, PID: 2429
    java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
        at android.view.ViewGroup.addViewInner(ViewGroup.java:4954)
        at android.view.ViewGroup.addView(ViewGroup.java:4785)
        at androidx.viewpager.widget.ViewPager.addView(ViewPager.java:1485)
        at android.view.ViewGroup.addView(ViewGroup.java:4725)
        at android.view.ViewGroup.addView(ViewGroup.java:4698)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:326)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
        at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2625)
        at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2577)
        at androidx.fragment.app.Fragment.performActivityCreated(Fragment.java:2722)
        at androidx.fragment.app.FragmentStateManager.activityCreated(FragmentStateManager.java:346)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1188)
        at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
        at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6719)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:449)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

But all code for transition fragment and data binding is generated automatically. I do not known where i must call removeView().

If you try to use old dependencies, then invert all comments in code and layouts. And popBackStack() will work correctly.

I do not found anything about this error. May be, I do something incorrect?

The solution is just to add this code to every fragment:

@Override
public void onDestroyView() {
    super.onDestroyView();
    if(binding.getRoot().getParent() != null)
        ((ViewGroup)binding.getRoot().getParent()).removeView(binding.getRoot());
}

I really recommend you to create a BaseFragment which has this code and every fragment will extends from it, so you will not have to repeat the code on every fragment class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM