Android应用中使用Fragment组件的一些问题及解决方案总结

2019-12-10 18:03:22丽君

FragmentTransaction

  • 对于Fragment的操作都是通过FragmentTransaction来进行的,一个FragmentTransaction可以包含一个或者多个操作,通过commit或者commitAllowingStateLoss来提交.如果该FragmentTransaction被加入返回栈,那么出栈的时候,该Transaction中的所有操作都会被撤销
  • commit方法是异步的(handler post相应的message到MainLooper关联的Message queue),如果需要立刻执行Transaction的操作,可以调用executePendingTransactions()
  • FragmentTransaction的commit方法以及FragmentManager的popBackStack方法都是异步的,给调用者带来了很多不便,虽然可以通过调用executePendingTransactions()方法来立即执行,但是为什么默认是异步的呢??(我觉得是因为:提交一个Transaction,会导致Fragment的生命周期方法的执行,甚至是多个回调的执行,如果Fragment在这些回调中又提交新的Transaction,那么可能会破坏当前Transaction的状态,比方说这是一个pop操作)

    Can not perform this action after onSaveInstanceState

    在使用Fragment的过程中,常常会遇到在Activity的onSaveInstanceState方法调用之后,操作commit或者popBackStack而导致的crash.
    因为在onSaveInstanceState方法之后的操作状态可能会丢失,因此Android framework默认会抛出一个异常.
    对于commit方法来说,单纯避免这个异常很简单,使用commitAllowingStateLoss方法即可.但是popBackStack以及popBackStackImmediate也都会检查state(checkStateLoss),特别需要注意的是Activity的onBackPressed方法

    public void onBackPressed() {
      if (!mFragments.popBackStackImmediate()) {//注意
        supportFinishAfterTransition();
      }
    }
    

    如果onBackPressed在onSavedInstanceState之后调用,那么就会crash.
    onBackPressed的调用时机:

    * targetSdkVersion <= 5,在onKeyDown中调用
    * targetSdkVersion > 5,在onKeyUp中调用
    onSavedInstanceState的调用时机(如果调用的话):

    * 一定在onStop之前
    * 可能在onPause之前,也可能在onPause与onStop之间