zoukankan      html  css  js  c++  java
  • Android 异常情况下的生命周期分析

    异常情况下的生命周期分析

    一:资源相关的系统配置发生改变导致Activity被杀死并重新创建(以旋转屏幕为例)

    样例代码,

    首先再onSaveInstanceState中存储一个字符串,然后当 Activity被销毁并重新创建的时后,再去获取之前存储的字符串。接收的位置可以在 onRestoreInstanceState 或者onCreate,二者的区别是: onRestoreInstanceState 一旦被调用其参数Bundle savedInstanceState一定是有值的,不需要额外判空;但onCreate不行,因为onCreate如果是正常启动,其参数Bundle savedInstanceStatenull,所以必须进行额外判断。官方推荐采用 onRestoreInstanceState 进行恢复数据。

    	@Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            if (savedInstanceState != null){
                String test = savedInstanceState.getString("test");
                Log.d(TAG, "[onCreate] restore extra_test: " + test);
            }
        }
    
        @Override
        protected void onSaveInstanceState(Bundle outState){
            super.onSaveInstanceState(outState);
            Log.d(TAG,"onSaveInstanceState");
            outState.putString("test","test");
        }
    
        @Override
        protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
            super.onRestoreInstanceState(savedInstanceState);
            String test = savedInstanceState.getString("test");
            Log.d(TAG,"[onRestoreInstanceState] restore test: " + test);
        }
    

    当旋转屏幕后,运行的日志如下:

    日志分析

    当系统配置发生改变后,Activity 会被销毁,其onPause、onStop、onDestroy 均会被调用,同时由于Activity 是在异常情况下终止的,系统会调用 onSaveInstanceState 来保存当前Activity的状态。这个方法的调用时机是在 onStop 之前,它和 onPause 没有既定的时序关系,它既可能在onPause之前调用,也可能在onPause之后调用。(当Android api为28时,onStop会在其之前,即 onSaveInstanceState 出现在 onStop之后,onDestroy之前,与日志情况相符)需要强调的一点是,这个方法只会出现在Activity 被异常终止的情况下,正常情况下系统不会回调这个方法。当 Activity 被重新创建后,系统会调用 onRestoreInstanceState, 并且把Activity 销毁时onSavelnstanceState 方法所保存的Bundle 对象作为参数同时传递给 onRestoreInstanceState和 onCreate 方法。因此,我们可以通过 onRestoreInstanceState 和 onCreate 方法来判断Activity是否被重建了,如果被重建了,那么我们就可以取出之前保存的数据并恢复,从时序上来说,onRestorelnstanceState 的调用时机在onStart之后。

    onSaveInstanceState调用时机

    1. 当用户按下HOME键时。 这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则
    2. 长按HOME键,选择运行其他的程序时
    3. 按下电源按键(关闭屏幕显示)时
    4. 从activity A中启动一个新的activity时
    5. 屏幕方向切换时,例如从竖屏切换到横屏时。

    onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)

    避免当系统配置发生改变后,Activity被重新创建

    configChanges属性添加值

    例如解决旋转屏幕的重新创建:android:configChanges="orientation|screenSize"

    主要使用的几个值

    • keyboardHidden : 键盘的可访问性发生了改变,例如调出了键盘
    • orientation : 屏幕方向发生了改变,例如旋转了屏幕
    • screenSize : 当屏幕的尺寸信息发省了改变,当旋转屏幕时,屏幕尺寸会发生改变,但这个选项比较特殊和编译选项有关,当编译选项中的 minSdkVersion 和 targetSdkVersion 均低于13时,此选项不会导致 Activity 重启,否则会导致 Activity 重启(API 13 新添加)
    • locale : 设备的本地位置发生了改变,一般指切换了系统语言

    二:资源内存不足情况导致低优先级的Activity被杀死

    这种情况我们不好模拟,但是其数据存储和恢复过程和情况一完全一致。这里我们描述一下Activity的优先级情况。Activity 按照优先级从高到低,可以分为如下三种:

    1. 前台Activity-- 正在和用户交互的Activity, 优先级最高。

    2. 可见但非前台Activity——比如 Activity中弹出了一个对话框,导致Activity可见,但是位于后台无法和用户直接交互。

    3. 后台Activity--已经 被暂停的Activity,比如执行了onStop, 优先级最低。

    当系统内存不足时,系统就会按照上述优先级去杀死目标 Activity 所在的进程,并在后续通过 onSaveInstanceState 和 onRestoreInstanceState 来存储和恢复数数据。如果一个进程中没有四大组件在执行,那么这个进程将很快被系统杀死,因此,一些后台工作不适合脱离四大组件而独自运行在后台中,这样进程很容易被杀死。比较好的方法是将后台工作放入Service中从而保证进程有一定的优先级,这样就不会轻易地被系统杀死。

  • 相关阅读:
    socket based————转帖
    罗马假日 java程序员
    java六大必须理解的问题来自网络少许有误 java程序员
    spring的scope="prototype" java程序员
    @GeneratedValue java程序员
    myeclipse乱码和tomcat相关的 java程序员
    关于***.hbm.xml的说明 java程序员
    hibernate中的Annotation补充 java程序员
    爱的随笔C语言版 java程序员
    Hibernate对jpa annotation的支持 java程序员
  • 原文地址:https://www.cnblogs.com/huaranmeng/p/13804144.html
Copyright © 2011-2022 走看看