TensorFlow 2 文档 TensorFlow 2 教程 Python 简明教程 Go 语言简明教程 Go 面试题 Go 高性能编程

android Activity生命周期(设备旋转、数据恢复等)与启动模式

博客逐步迁移至 极客兔兔的小站

1.Activity生命周期

    接下来将介绍 Android Activity(四大组件之一) 的生命周期, 包含运行、暂停和停止三种状态,onCreate、onStart、onResume、onPause、onStop、onDestroy六种系统调用方法。

1.1 Activity生命周期简介与测试

生命周期

    如图所示,Activity实例可以在生命周期状态发生关键性转换时完成某些工作。

  • onCreate() 创建,该方法是最常被覆盖的方法,第一次创建实例时调用, 一般用来完成实例创建的初始化操作,包括实例化组件,设置监听器,访问外部模型数据等。
  • onStart() 开始,当Activity处于可见状态的时候就会调用onStart方法,包括创建完实例显示,或者从其他活动切换到活动时调用。
  • onResume() 准备,当Activity获得用户焦点时调用。
  • onPause 暂停,当Activity准备调用或者恢复另一个活动时调用,失去焦点时,例如启动一个Dialog调用。该方法可以释放一些消耗CPU的资源,保存一些关键数据,但是执行速度要快,否则影响新的栈顶活动使用。
  • onStop 停止,完全不可见时调用。例如成功启动了另外一个活动,该活动离开栈顶不可见。启动Dialog不会执行该方法。
  • onDestroy 销毁,这个方法在活动销毁时调用。
// 可以使用以下方法进行测试。
public class MainActivity extends Activity {
    
    private String TAG = "MainActivity";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG,"Create");
    }
    
    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "Start");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "Resume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "Pause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "Stop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "Destroy");
    }
}

1.2 设备旋转时的生命周期与数据恢复

设备旋转

    使用上面的日志打印测试方法发现, 设备旋转时生命周期如图所示,即设备旋转时,当前活动实例会被系统销毁,然后创建一个新的实例。

    因为旋转设备会改变设备配置(device configuration),设备配置包括屏幕的方向、密度、尺寸、键盘类型、底座模式等,为匹配不同的设备,可以使用不同的布局文件,这和Web开发中 针对不同宽度的屏幕选择不同CSS样式异曲同工,如何创建不同布局适配不同配置设备不在本文讨论之列。

    设备旋转时,临时数据会丢失。例如你使用了一个变量记录了用户点击了多少次按钮,设备旋转之后,Activity重新创建,这个变量就被初始化了,这里可以使用Bundle对象来恢复。保存数据可以覆盖onSaveInstanceState()方法。

    例如下面的代码,按3次按钮,旋转屏幕后,将打印出saved currentPage:3 init mCurrentPage:0,点击次数存在了Bundle对象中,并在onCreate()中获取到。

/*
 * onSaveInstanceState()通常在onPause、onStop、onDestroy前由系统调用
 * onCreate()传入的参数savedInstanceState可获取保存的变量
 */
public class MainActivity extends Activity {

    private static final String KEY = "currentPage";
    private static final String TAG = "MainActivity";
    private Integer mCurrentPage = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCurrentPage += 1;
            }
        });
        if(savedInstanceState != null){
            // 打印使用Bundle保存的currentPage信息
            Log.d(TAG,"saved currentPage: " + savedInstanceState.getInt(KEY,0));
            // 打印新建活动mCurrentPage的值,总为0
            Log.d(TAG,"init mCurrentPage: " + mCurrentPage);
            // ... update code
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        // 使用key-value对的方式存储临时变量
        outState.putInt(KEY, mCurrentPage);
    }
}

1.3 Activity暂存与Activity记录

    当系统回收内存时,处于Pause、Stop状态的Activity可能被销毁,此时系统会调用onSaveInstanceState(),用户数据被存储在Bundle对象中,系统将Bundle对象放入Activity记录,可以将这种状态理解为Activity的暂存状态(无实例有记录)。

    Activity暂存后,当前活动不复存在,Activity记录可帮助用户返回应用时活动的快速恢复,提供一个好的用户体验。但是当用户按了后退键,系统会彻底销毁当前活动,Activity记录同时被清除,系统重启也会被清除该记录。

2.Activity启动模式

2.1 standard(默认)

     standard是活动默认的启动模式,Android是使用返回栈来管理活动的,所谓栈就是先进后出,后进先出。该模式下,每启动一个新的活动,就会在返回栈中入栈,并处于栈顶的位置(即用户当前见到的活动)。系统不会 检查该活动的实例已经在返回栈中存在,每次启动都新建一个。当前返回栈为A->B(B为栈顶),新建活动B, 返回栈变为A->B->B。

2.2 singleTop

    standard模式有时并不合理,比如活动实例已经在栈顶了,再次启动时还需再创建一个实例, 这会造成资源的浪费。singleTop模式下,如果当前栈顶已经是该活动实例,则认为可以直接使用,而不再创建新的活动。当前返回栈为A->B(B为栈顶),新建活动B, 返回栈仍为A->B。

<!--AndroidManifest.xml-->
<!--设置方式,launchMode -->
<activity android:name=".MainActivity"
    android:launchMode="singleTop"
    android:label="AndroidDialog">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

2.3 singleTask

    singleTop模式可以避免重复创建栈顶活动的问题,但是如果启动活动不在栈顶,而之前已经创建过,还是会重复创建。例如A->B->C,当前已有三个活动A、B、C,C位于栈顶,再创建B,返回栈变为A->B->C->B(另一个实例)。singleTask模式可以让返回栈中每个活动只存在一个实例,如果发现当前需要启动活动已经在栈中,则直接使用,但是该活动之上的所有活动全部出栈;如没有发现,则创建新的实例。例如A->B->C,如此时创建活动B,则返回栈变为A->B(B存在,使用B,C出栈);若此时创建活动D,则返回栈变为A->B->C->D

2.4 singleInstance

    singleInstance模式是四种启动模式中最复杂的,不同于上述三种模式,指定为singleInstance模式的活动会启动一个新的返回栈来管理这个活动。例如当前有活动A、B、C,活动A、C为默认启动模式,B指定为singleInstance模式,首先新建A,A活动页面启动B,B启动C,此时的返回栈并不是A->B->C,而是存在2个返回栈,一个是A->C,另一个是B。此时按下BACK键返回,将从C返回到A,再按一次,A返回到B,按第三次,程序退出。即返回时,先清空栈A->C,再清空栈B。
    singleInstance模式有什么应用场景呢?例如当前程序中某个活动允许其他活动调用,如果想多个程序共享该活动的一个实例A,那么每一个程序都有一个返回栈,若使用前3种模式,该活动入栈时必然创建新的实例,无法实现实例共享。singleInstance能很好地解决这个问题。

posted @ 2016-03-08 18:23  呆尐兔兔  阅读(2644)  评论(0编辑  收藏  举报