Activity和Fragment的生命周期总结以及保存实例状态机制

读完将收获以下内容

一. Activity的生命周期详解
Activity配置和状态改变时生命周期
Activity状态和配置改变时的解决方案
二.Fragment的生命周期详解
Fragment配置和状态改变时生命周期
Fragmen状态和配置改变时的解决方案
三.Activity和Fragment的生命周期调用顺序

一. Activity的生命周期详解

生命周期基础

详细可以看:

Activity生命周期

Activity配置和状态改变时生命周期

背景:

如果系统由于系统约束(而不是正常的应用程序行为)而破坏了Activity,那么尽管实际 Activity实例已经消失,但是系统还是会记住它已经存在,这样如果用户导航回到它,系统就会创建一个新的Activity实例,并使用一组保存的数据来描述Activity在被销毁时的状态。系统用于恢复以前状态的已保存数据称为“实例状态”,是存储在Bundle对象中的键值对的集合(IPC 对 Bundle 有 1M 的限制,不宜存放大内存数据,viewmodel的存放数据能力也是它的一个优势)

不正常销毁解决方案:

onSaveInstanceState(@NonNull Bundle outState)

onRestoreInstanceState()

在这里插入图片描述

Activity提供了上面这俩个方法来解决 Activity的不正常销毁。

简单使用:

  1. 重写 onSaveInstanceState
    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
    
    
    //利用outstate保存需要的数据
        outState.putString("text",(String) mtv.getText());
        Log.d("jian", "Activity onSaveInstanceState: ");
    //outState.putSerializable("fragment",fragment);
        super.onSaveInstanceState(outState);
    // 调用父类交给系统处理,这样系统能保存视图层次结构状态
    }

  1. 在onCreate(@Nullable Bundle savedInstanceState) 中:
       //savedInstanceState就是onCreate的参数了
       //在oncreate中,savedInstanceState可能为null,所以需要判空
        if(savedInstanceState != null){
    
    
            String text = savedInstanceState.getString("text");
            mtv.setText(text);
        }

或者在onRestoreInstanceState(@NonNull Bundle savedInstanceState) 中:
onRestoreInstanceState 只有在activity被系统回收或是销毁的时候.重新创建activity的情况下才会被调用。

           //注意这个方法里的savedInstanceState一定不为null
           //因为只有在Activity被不正常销毁后重建的时候才会调用,所以此时方法参数一定不为null,因此不需要判空
           
            super.onRestoreInstanceState(savedInstanceState);            
            // 总是调用超类,以便它可以恢复视图层次超级
            String text = savedInstanceState.getString("text");
            mtv.setText(text);

onCreate和onRestoreInstanceState方法的区别:

  • 因为onSaveInstanceState 不一定会被调用,所以onCreate()里的Bundle参数可能为空,如果在onCreate中来恢复数据,savedInstanceState一定要做非空判断。

  • onRestoreInstanceState的Bundle参数一定不会是空值,因为它只有在上次activity被回收了才会调用。

  • onRestoreInstanceState是在onStart()之后被调用的。有时候我们需要onCreate()中做的一些初始化完成之后再恢复数据,用onRestoreInstanceState会比较方便。
    简单看一下Activity生命周期方法的调用顺序:

  • 刚打开Activity:
    onCreate --> onStart --> onResume
    在这里插入图片描述

    扫描二维码关注公众号,回复: 14844928 查看本文章
  • 旋转屏幕时:
    onPause --> onSaveInstanceState --> onStop–> onDestroy --> onCreate --> onStart --> onRestoreInstanceState–> onResume
    在这里插入图片描述

  • 按下返回键时:
    其实按下返回键时,系统调用的是finish()
    onPause-> onStop–> onDestroy
    在这里插入图片描述

  • 按下返回键后再重新打开activity
    onCreate --> onStart --> onResume
    在这里插入图片描述
    所以综上可知,

  • 按下返回键系统调用的是finish,另外,不管是按下返回键(系统调用了finish() )或者用户自己调用finish() 都是属于正常关闭activity,因此onSaveInstanceState()方法 此时不会调用,当此时重新进入(创建) activity时,onRestoreInstanceState(@NonNull Bundle savedInstanceState)方法也不会被调用

  • 不管是按下返回键(系统调用了finish() )或者用户自己调用finish() 都是属于正常关闭activity/fragment,此时activity/fragment都是会被销毁onDestory,重新进入时会onCreate,此时创建的实例与销毁前的实例不一样

配置状态改变时解决方案:

onRetainNonConfigurationInstance

public final Object onRetainNonConfigurationInstance() 

getLastNonConfigurationInstance

    public Object getLastNonConfigurationInstance() {
    
    
        return mLastNonConfigurationInstances != null
                ? mLastNonConfigurationInstances.activity : null;
    }

由于onRetainNonConfigurationInstance是final修饰的不可以重写,但是如果想在 Activity 中自定义想要恢复的数据,我们可以使用上述两个方法的内部方法

  • onRetainCustomNonConfigurationInstance()方法
    @Deprecated
    @Nullable
    public Object onRetainCustomNonConfigurationInstance() {
    
    
        return null;
    }

需要重写,重写后系统会帮我们调用,介于onStop和onDestory之间
在这里插入图片描述

  • getLastCustomNonConfigurationInstance()方法
    可以重写(一般不用重写),但是需要自行调用,只能在onCreate到onStart之间调用,超出范围如在onResume中调用则无效,获取不到任何东西
    @Deprecated
    @Nullable
    public Object getLastCustomNonConfigurationInstance() {
    
    
        NonConfigurationInstances nc = (NonConfigurationInstances)
                getLastNonConfigurationInstance();
        return nc != null ? nc.custom : null;
    }

简单使用:

  1. 重写onRetainCustomNonConfigurationInstance()

    @Nullable
    @Override
    public Object onRetainCustomNonConfigurationInstance() {
    
    
        nums = 10;
        Log.d("jian", "Activity onRetainCustomNonConfigurationInstance: ");
        //将数据分装成对象放进来
        return Integer.valueOf(nums);
    }
  1. 调用getLastCustomNonConfigurationInstance()
  • 可以在onStart() 中调用
    @Override
    protected void onStart() {
    
    
        super.onStart();
        Log.d("jian", "Activity onStart: ");
        Integer nums = (Integer)getLastCustomNonConfigurationInstance();
        Log.d("jian", "onStart: " + nums);
    }
  • 可以在onCreate()中调用,使用方法同上,记得强转类型
  • 注意在onResume()中调用的话拿到的是null

二.Fragment的生命周期详解

fragment的生命周期图( Activity 运行时)

在这里插入图片描述

Activity 生命周期对Fragment生命周期的影响图

在这里插入图片描述

简单演示:

  • 进入:
    在这里插入图片描述
  • 按下返回键
    在这里插入图片描述
    生命周期可自行演示,文章重点放在配置改变时的数据恢复上

fragment配置状态改变时数据恢复解决方案(如当旋转屏幕时):

onSaveInstanceState(@NonNull Bundle outState)

Fragment同样也提供了onSaveInstanceState方法介于onPause和onStop之间
在这里插入图片描述
不同的是:

  1. 无 **onRestoreInstanceState(@NonNull Bundle savedInstanceState)**方法
  2. 可以在onCreate, onCreateView, onActivityCreated中做数据恢复
    在这里插入图片描述
    使用方法跟Activity一样,不再演示

Fragment 的 setRetainInstance:

当配置发生改变时,Fragment 会随着宿主 Activity 销毁与重建,当我们调用 Fragment 中的 setRetainInstance(true) 方法时,系统允许 Fragment 绕开销毁-重建的过程。使用该方法,将会发送信号给系统,让 Activity 重建时,保留 Fragment 的实例。需要注意的是:

  • setRetainInstance(true) 一定要在 onSaveInstanceState方法被调用之前调用才有效,即在onPause中或者之前调用才有效
    在这里插入图片描述

  • 若在onSaveInstanceState中或者之后调用,则Fragment还是会销毁重建,从下图打印的log就可以知道重建后的实例跟销毁的实例不一样
    在这里插入图片描述

从上面的生命周期方法调用顺序可知

  • 调用setRetainInstance(true)后,不会调用 Fragment 的 onDestory() 方法,但仍然会调用 onDetach() 方法
  • 调用setRetainInstance(true)后,不会调用 Fragment 的 onCreate(Bundle) 方法。因为 Fragment 没有被重建。
  • 调用setRetainInstance(true)后,Fragment 的 onAttach(Activity) 与 onActivityCreated(Bundle) 方法仍然会被调用。

三.Activity和Fragment的生命周期调用顺序

  • 刚进入
    在这里插入图片描述

  • 按下Home键
    在这里插入图片描述

  • 按下Home键后重新进入
    在这里插入图片描述

  • 按下返回键
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/XJ200012/article/details/128615974