• Android开发基础:Activity的生命周期 Activity中的数据保持


    目录

    一,Activity的生命周期

    1.Activity活动栈

     2.Activity状态

    3.Activity状态之间的切换

     4.代码实例体验Activity生命周期

    二,Activity中的数据保持

    1.onSaveInstanceState()


    一,Activity的生命周期

    1.Activity活动栈

            众所周知,Android中的Activity是可以层叠的,当我们启动一个新的Activity时,就会叠加在旧的Activity上,点击Back销毁Activity,上一个Activity就会重新显示出来,之所以会这样,是因为Android是使用活动栈(也叫返回栈)来管理Activity的。

            每启动一个新的Activity,它就会在活动栈中入栈,并处于栈顶位置,按下Back健销毁Activity后,它就会出栈,下一个Activity就会重新处于栈顶位置,屏幕上显示的总是栈顶的Activity。

     2.Activity状态

    Activity在内存中右四种存在状态:

    (1)运行状态

            当Activity处于活动栈栈顶时,Activity就处于运行状态。此时的Activity需要和用户进行交互,所以系统尽可能不会回收处于运行状态的Activity。

    (2)暂停状态

            当Activity不再处于栈顶位置,但是仍然可见时,就处于暂停状态。例如弹出对话框时,对话框下面的Activity就处于暂停状态。因为暂停状态的Activity仍然可见,所以系统也是尽可能不会回收暂停状态的Activity,除非内存极低的情况,系统才会考虑回收。

    (3)停止状态

            当Activity不再处于栈顶位置,并且不可见时,就处于停止状态。因为处于停止状态的Activity可能会被重新启动,所以系统会为这种Activity保存用户状态信息,但当系统内存不够时,会优先杀死该类Activity。

    (4)销毁状态

            当Activity从活动栈中移除时就变成了销毁状态。系统会回收该类Activity以保证内存充足。

    3.Activity状态之间的切换

            Activity类中定义了七个回调方法,覆盖率Activity生命周期的每一个环节,每当Activity的状态改变时,这些方法就会被调用:

    1. onCreate():创建方法。在Activity第一次被创建时调用,每当我们创建一个新的Activity时,都会重写一次onCreate方法。在这个方法中应当完成加载布局和绑定事件等操作;
    2. onStart():启动方法。在Activity每次由不可见变为可见时调用;
    3. onResume():在Activity准备好与用户交互时调用,此时Activity一定位于活动栈的栈顶,并且处于运行状态;
    4. onPause():暂停方法。在系统准备去启动或者恢复另一个Activity时调用,或者说是当前Activity进入暂停状态之前调用。通常会在这个方法中将一些消耗CPU的资源释放,以及保存一些关键数据。这个方法的执行速度一定要快,否则会影响到新的Activity的使用;
    5. onStop():停止方法。这个方法在Activity完全不可见时调用。
    6. onDestroy():销毁方法。在Activity销毁之前调用。
    7. onRestart();重启方法。在Activity由停止状态变为运行状态之前调用,重启之后Activity重新位于活动栈栈顶,被用户可见;

     

     4.代码实例体验Activity生命周期

    我们可以在Activity中重写这七个回调方法,以此来更直观地来体验Activity的生命周期。

    (1)分别创建NormalActivity和DialogActivity两个新的Activity,作为要跳转的Activity。其中,DialogActivity作为对话框式的Activity,在AndroidManifest.xml文件中按如下设置:

    1. <activity
    2. android:name=".DialogActivity"
    3. android:theme="@style/Theme.AppCompat.Dialog"
    4. android:exported="true" />

    NormalActivity布局文件:

    1. "1.0" encoding="utf-8"?>
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3. android:layout_width="match_parent"
    4. android:layout_height="match_parent">
    5. <TextView
    6. android:layout_width="match_parent"
    7. android:layout_height="wrap_content"
    8. android:text="This is NormalActivity"
    9. android:textSize="25sp"/>
    10. LinearLayout>

    DialogActivity布局文件:

    1. "1.0" encoding="utf-8"?>
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3. android:layout_width="match_parent"
    4. android:layout_height="match_parent">
    5. <TextView
    6. android:layout_width="match_parent"
    7. android:layout_height="wrap_content"
    8. android:text="This is DialogActivity"
    9. android:textSize="25sp"/>
    10. LinearLayout>

    (2)以MainActivity作为主Activity,在布局文件中设置两个按钮,分别用于启动NormalActivity和DialogActivity,并在Activity中给按钮绑定监听器:

    1. "1.0" encoding="utf-8"?>
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3. android:layout_width="match_parent"
    4. android:layout_height="match_parent"
    5. android:orientation="vertical">
    6. <Button
    7. android:id="@+id/btn_jumpToNormalActivity"
    8. android:layout_width="match_parent"
    9. android:layout_height="wrap_content"
    10. android:text="跳转到NormalActivity"
    11. android:textSize="25sp"/>
    12. <Button
    13. android:id="@+id/btn_jumpToDialogActivity"
    14. android:layout_width="match_parent"
    15. android:layout_height="wrap_content"
    16. android:text="跳转到DialogActivity"
    17. android:textSize="25sp"/>
    18. LinearLayout>
    1. //跳转到Normal
    2. btn_jumpToNormalActivity.setOnClickListener(new View.OnClickListener() {
    3. @Override
    4. public void onClick(View v) {
    5. jumpToNormalActivity();
    6. }
    7. });
    8. //跳转到DialogActivity
    9. btn_jumpToDialogActivity.setOnClickListener(new View.OnClickListener() {
    10. @Override
    11. public void onClick(View v) {
    12. jumpToDialogActivity();
    13. }
    14. });
    15. private void jumpToDialogActivity() {
    16. Intent intent = new Intent();
    17. intent.setClass(this, DialogActivity.class);
    18. startActivity(intent);
    19. }
    20. private void jumpToNormalActivity() {
    21. Intent intent = new Intent();
    22. intent.setClass(this, NormalActivity.class);
    23. startActivity(intent);
    24. }

    (3)最后在MainActivity中重写七个回调方法:

    1. @Override
    2. protected void onCreate(Bundle savedInstanceState) {
    3. super.onCreate(savedInstanceState);
    4. setContentView(R.layout.activity_main);
    5. Log.i("msg114514", "MainActivity:onCreate");
    6. }
    7. @Override
    8. protected void onStart() {
    9. Log.i("msg114514", "MainActivity:onStrat");
    10. super.onStart();
    11. }
    12. @Override
    13. protected void onRestart() {
    14. Log.i("msg114514", "MainActivity:onRestart");
    15. super.onRestart();
    16. }
    17. @Override
    18. protected void onResume() {
    19. Log.i("msg114514", "MainActivity:onResume");
    20. super.onResume();
    21. }
    22. @Override
    23. protected void onPause() {
    24. Log.i("msg114514", "MainActivity:onPause");
    25. super.onPause();
    26. }
    27. @Override
    28. protected void onStop() {
    29. Log.i("msg114514", "MainActivity:onStop");
    30. super.onStop();
    31. }
    32. @Override
    33. protected void onDestroy() {
    34. Log.i("msg114514", "MainActivity:onDestroy");
    35. super.onDestroy();
    36. }

    接着我们就可以通过日志打印来观察Activity的生命周期了。

    (1)首先,启动Activity,观察Logcat可以看到当MainActivity第一次被创建时会依次执行onCreateonStartOnResume三种方法,因为这时Activity刚被创建出来,由不可见变为了可见,并且准备好了与用户进行交互;

    (2)点击按钮,启动NormalActivity,可以看到onPauseonStop方法被调用,因为这时另一个Activity被启动,并且MainActivity变为不可见状态,即进入停止状态;

    (3)按下Back键返回MainActivity,观察到onRestartonStartonResume方法被调用,因为这时MainActivity由停止状态变为了运行状态,并且重新准备好了与用户进行交互;

    (4)点击第二个按钮,启动DialogActivity,此时只有onPause方法被调用,因为MainActivity此时仍能被用户可见,也就是进入了暂停状态;

    (5)按下Back键返回MainActivity,发现只有onResume方法被调用,因为之前MainActivity并没有进入停止状态;

    (6)最后在MainActivity按下Back键退出程序,此时会依次执行onPauseonStoponDestroy方法,因为MainActivity变为了不可见状态,并且退出程序后MainActivity被销毁;

     至此,我们就完整地体验了一遍Activity的生命周期。

    二,Activity中的数据保持

            试想以下这种情况,我们在一个编辑框EditView中编写好了一些内容,但这时发生了一些突发情况使Activity进入了停止状态甚至被销毁(如:不小心点到Back键,有电话突然打进来),从而变得不可见。当我们返回这个Activity时,如果编辑框中的内容消失了,肯定会给用户带来不好的体验,那么我们该如何对这些数据进行保持和恢复呢?

    1.onSaveInstanceState()

            Activity提供了一个onSaveInstanceState()回调方法用于保存并恢复一些临时数据,这里的临时数据包括EditText中的内容,视频播放进度等。onSaveInstanceState()方法会携带一个Bundle类型的参数,Bundle提供了一系列的方法用于保存数据。Bundle的保存方法需要传入两个参数,键值和要保存的内容,键值用于从Bundle中取出数据。

    public abstract void onSaveInstanceState(Bundle outState);

    onSaveInstanceState()的使用具体分为两步:数据的保存与恢复;

    (1)数据的保存:在Activity中重写onSaveInstanceState()方法;

    1. @Override
    2. public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
    3. super.onSaveInstanceState(outState, outPersistentState);
    4. String text = edt_text.getText().toString();
    5. outState.putString("edt_text", text);
    6. }

    (2)数据的取出:在我们平时一直使用的onCreate方法中有一个Bundle类型的参数savedInstanceState,我们可以通过这个参数来实现对数据的取出,取出时需要判断savedInstanceState是否为空;

    1. @Override
    2. protected void onCreate(Bundle savedInstanceState) {
    3. super.onCreate(savedInstanceState);
    4. setContentView(R.layout.activity_main);
    5. if(savedInstanceState != null){
    6. String text = savedInstanceState.getString("edt_text");
    7. edt_text.setText(text);
    8. }
    9. }

            然而实际上对于View我们并不需要进行这些操作,因为Android的View自身已经实现onSaveInstanceState()方法,这些控件本身就具有保存和恢复数据的功能,例如TextView中:

  • 相关阅读:
    《性能之巅第2版》阅读笔记(二)--性能观察工具
    android 通过onActivityResult,调用react native 的函数
    Java基于PHP+MySQL干洗店管理系统的设计与实现
    openvino多输入多输出动态尺寸样例记录
    PCL 使用克拉默法则进行三点定圆(二维)
    Java版直播商城免 费 搭 建:电商、小程序、三级分销及免 费 搭 建,平台规划与营销策略全掌握
    Android组件通信——广播机制:BroadcastReceiver(二十九)
    activiti7 报错Couldn‘t resolve collection expression nor variable reference
    Twins: Revisiting the Design of Spatial Attention in Vision Transformers
    java.lang.Float类下isNaN(float v)方法具有什么功能呢?
  • 原文地址:https://blog.csdn.net/IH_LZH/article/details/138037340