• Android(java)学习笔记113:Activity的生命周期


    1.首先来一张生命周期的总图:

    onCreate():创建Acitivity界面

          onStart():让上面创建的界面可见

                 onResume():让上面创建的界面中的点击事件生效获得焦点

                 onPause():让上面创建的界面中的点击事件没有效果失去焦点

          onStop():让上面创建的界面不可见(最小化)

    onDestory():销毁上面的创建的界面

    (1)完整生命周期(entire lifetime):

    onCreate()---> onStart()-->onResume()-->onPause()-->onStop()-->onDestory()

    (2)可视生命周期(visible lifetime):

    onStart()-->onResume()-->onPause()-->onStop()

    (3)前台生命周期(foreground lifetime):

    onResume-->onPause()

    2.几个典型的场景

    (1)Activity从被装载到运行,执行顺序如下:

    onCreate()  ->    onStart() ->  onResume();

    (2)Activity从运行到暂停,再到继续回到运行

    onPause() ->  onResume ()

           这个过程发生在Activity被别的Activity遮住了部分UI,失去了用户焦点,另外那个Activity退出之后,这个Activity再次获得运行。整个过程中,该Activity的实例是一直存在的。

    (3)Activity运行到停止

    onPause() -> onStop()

    这个过程发生在Activity的UI完全被别的Activity遮住了,当然也失去了用户的焦点。这个过程中Activity的实例仍然存在。比如,当Activity运行的时候,用户了按了Home键,该Acitivity就会被执行。

     (4)Activity从停止到运行

    onReset() ->  onStart() -> onResume() 

    处于Stopped状态并且实例仍然存在的Activity,再次被系统运行时,执行这个过程。这个过程是(3)的逆过程。

    (5)Activity从运行到销毁,执行顺序如下:

    onPause() ->  onStop() -> onDestory()

    这个过程发生在Activity完全停掉并被销毁了,所以该Activity的实例也就不存在了。比如这个Activity正在运行,用户按了Back按键,该Activity就会执行这个过程。这个过程是(1)的逆过程。

    (6)被清除出内存的Activity的重新运行

    onCreate() -> onStart() -> onResume()

    这个过程对用户是透明的,用户不知道这个过程的发生。

    3. 在谷歌官方文档中,这样说道每个生命周期方法的作用:

    (1)onCreate
      当activity第一次创建时调用.这里应该完成所有静态资源的建立, 比如使用setContentView(int)和布局资源定义你的UI视图, 使用findViewById(int)取出程序中需要交互的控件, 绑定数据.
      此时视图还不存在,无法调用动画等.
      还有需要注意, 每次activity启动, 不一定都会调用这个函数. 当当前activity只是被覆盖一部分, 当前activity再次可交互时,是只调用onResume方法, 不会调用onCreate方法.
    (2) onStart
      这里说明它不是activity对用户是否可见的最好的指示器
    (3)onResume
      打开独占设备,如相机,在onPause中释放.
    (4)onPause
      在这里系统将要离开当前Activity, 恢复其他activity. 用户在程序里做的任何改变都应该在此刻提交(通常用ContentProvide来保存数据). 还有需要在这里停止动画和其他耗费CPU的事件来确保转换到下一个activity的流畅度.
      请记住:这个方法的实现必须很快完成, 不能占用太多时间, 因为在这个方法完成之前, 下一个activity不会恢复. 如果这个方法耗时较长, 就会影响用户体验. 如果对应的onPause()在500ms内还没有执行完,ActivityManagerService就会强制关闭这个Activity.
      另外一个请记住的是:如果当前activity拥有独占资源(比如相机), 必须在这里释放, 以免在下一个activity中需要用到.
    (5)onStop
      请注意: 在内存不足而导致系统无法保留此进程的情况下, onStop() 可能不会被执行。

    几乎所有Activity的子类,都会实现onCreate和onPause这两个方法.

    4. 几个关于Activity生命周期方法的疑问 ?

    (1)如果所有的初始化都在onCreate()中实现,会有什么问题?

      首先,Activity的onCreate()被调用时,Activity还不可见,如果要做一些动画,既然视图还不存在,在onCreate中来启动动画,明显有问题。

        其次,A Activity 切换到 B Activity,再切换到 A Activity(我们假定是A Activity的同一个实例),由于实例已经存在,所以onCreate不会再被调用,那A Activity从后台切换至前台时,有可能需要一些初始化,那就没法再被调用到了,也有问题。

    (2)如果所有的初始化都在onStart()中实现,会有什么问题?

      首先,onCreate()注释中,是明确建议 setContentView()、findViewById() 要在 onCreate() 中被调用,但我实测了一下,在onStart()中调用 setContentView()、findViewById() 功能也是正常的。

        其次,onStart() 被调用时,Activity可能是可见了,但还不是可交互的,onStart() 的注释中都明确地说了这不是Activity对用户是可见的最好的指示器,onStart() 在这之前被调用,那有一些特殊的初始化相关的逻辑在这里被调用也会有问题。

    (3)如果把所有的去初始化都在onStop()中实现,会有什么问题?

    • 在 onResume() 的注释中,建议是在onResume()中打开独占设备(比如相机),与onResume()对应的是onPause(),所以所有的去初始化操作放在onStop()中执行,可能会引出新的问题;
    • 在 onStop() 的注释中明确地写了,在内存不足而导致系统无法保留此进程的情况下,onStop() 可能都不会被执行。

        我的老Android手机的相机应用如果未正常关闭,相机在不重启系统的情况下就无法再正常启动,估计就和这个机制有关;相机进程是被强制杀掉的,而导致去初始化操作未被正常执行。

    (4)Activity间跳转时,为什么是先A Activity的onPause()被调用,然后是B Activity的初始化流程(onCreate() --> onStart() --> onResume()),再然后是A Activity的onStop()被调用

    • 在 onResume() 的注释中,建议是在onResume()中打开独占设备(比如相机),与onResume()对应的是onPause(),关闭相机的操作也应该在此方法中被调用;否则,考虑一下如下场景:

            如果A Activity打开了相机,我们点击某按钮要跳转到B Activity中,B Activity也想打开相机;假设A Activity的onPause() 在 BActivity启动后再被调用,

            那B Activity根本就无法再正常启动相机。

    • onPause() 的注释中,也明确地说了,在这个方法中执行停止动画等比较耗CPU的操作,如果不先执行这些操作,就先启动新应用,然后再来执行此操作,确实是不合逻辑;

    从A Activity切换到B Activity的日志如下:

    10-17 20:54:46.997: I/com.example.servicetest.A Activity(5817): onPause() 1166919192 taskID=66
    10-17 20:54:47.021: I/com.example.servicetest.B Activity(5817): onCreate() 1166971824 taskID=66
    10-17 20:54:47.028: I/com.example.servicetest.B Activity(5817): onStart() 1166971824 taskID=66
    10-17 20:54:47.028: I/com.example.servicetest.B Activity(5817): onResume() 1166971824 taskID=66
    10-17 20:54:47.099: I/com.example.servicetest.A Activity(5817): onStop() 1166919192 taskID=66

    从逻辑的完整性和用户体验的角度来分析,这样实现确实是比较合理的,当用户触发某事件切换到新的Activity,用户肯定是想尽快进入新的视图进行操作,

    上面已经说了,在onResume()一般会打开独占设备,开启动画等,

    当需要从AActivity切换到BActivity时,先执行AActivity中的与onResume()相对应的onPause()操作,比如关闭独占设备,关闭动画,或其它耗费cpu的操作;

    以防止BActivity也需要使用这些资源,关闭耗CPU的操作,也有利于BActivity运行的流畅

    底层执行AActivity的onPause()时,有一定的时间限制的,当ActivityManagerService通知应用进程暂停指定的Activity时,如果对应的onPause()在500ms内还没有执行完,ActivityManagerService就会强制关闭这个Activity。如下就是对应的onPause()执行超时常量定义:

    // How long we wait until giving up on the last activity to pause.  This  
    // is short because it directly impacts the responsiveness of starting the  
    // next activity.  
    static final int PAUSE_TIMEOUT = 500;  // 定义在ActivityStack.java中  

    A Activity中比较消耗资源的部分关闭后,再切换到B Activity中执行B Activity的初始化,显示B Activity中的View。

    当B Activity已经执行显示出来了,用户可以交互,后台再去执行A Activity的onStop()操作,即使这里面有些比较耗时的操作,也没有关系,这是在后台执行所以也不影响用户的体验

    A Activity跳转B Activity成功之后,如果用户点击Back键将依次执行B:onPause -> A:onRestart -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy。

    当然此时肯定是来到A Activity之中。

    接着上面,如果用户点击Home键,将依次执行A:onPause -> A:onStop。

    倘若上面用户不是点击Home键,而是再次点击Back键,那么系统返回到桌面,并依次执行A:onPause -> A:onStop -> A:onDestroy。

    5.Activity的实例化和启动

    Acitivity实例的工作是android系统完成的,在用户点击执行一个Activity或者另一个Activity需要这个Activity执行时,如果这个Activity的实例不存在,Android系统都会实例化之,并且在该Activity所在线程的主线程中调用Activity的onCreate()方法,实现Activity的工作。

    onCreate()是系统实例化Activity时,Activity可做的自身初始化的时机。在这里可以实例化变量,调用setContentView()设置UI显示内容。

    一般来说,在Activity实例化之后就好启动该Activity,这样会在该Activity所在的进程的主线程中顺序调用Activity的onStart(),onResume()。onCreate()在Acitivity存续期中,只会被调用一次。如生命周期图中时序(6)的情形其实是另外又开启一个Activity的实例,并通过onCreate的参数传递进先前杀掉的Acitivity保存的信息。因为onStart()可因为已经停止了,再次执行而被调用多次。onResume()可以因为Activity的Paused/Resumed的不停转换,而被频繁调用。

    6.Activity的暂停和继续

    7.Activity的关闭/销毁与重新运行

           因为处于Paused状态的Activity在内存极端不足的情况下,它所在的进程也可能被取消,这样onStop()在被取消前,不一定会被调用,这样的onPause()是比onStop()更适合的保留信息到永远存储区的时机

           Activity被销毁可能显式地按了Back按键,也可能是处于Paused或者Stopped状态,因为内存不足而被销毁。还有一种情况是配置信息改变(比如屏的方向改变)后,根据设置需要销毁掉所有的Activity(是否关闭还要看Activity自己的设置),再重新运行它们。

           被系统隐式销毁的Activity,在被销毁(onStop()调用)之前,一般的会调用onSaveInstanceState()保留该Activity此时的状态信息。该办法中传入一个参数Bundle,可以在此方法中把此时的状态信息写入,系统保留这些。而当该Activity再次被实例化运行时,系统会保留在Bundler的信息再次以参数形式,通过onCreate()方法传入。

    (1)onSaveInstanceState什么时候调用 

          通常在onSaveInstanceState()中保留UI信息,永久存储的信息最好还是在onPause()保存。Activity的onSaveInstanceState()已经缺省实现来保留通用View的UI信息,所以不管是否保留当前Activity的信息,通常都在onSaveInstanceState()中调用super.onSaveInstanceState()来保留通用的UI信息。 

      当某个activity变得"容易"被系统销毁时,该activity的onSaveInstanceState()就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候,onSaveInstanceState()就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。

       注意上面的双引号,何为"容易"?意思就是说该activity还没有被销毁,而仅仅是一种可能性。这种可能性有哪些?

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

      当屏幕的方向发生了改变, Activity会被摧毁并且被重新创建,如果你想在Activity被摧毁前缓存一些数据,并且在Activity被重新创建后恢复缓存的数据。可以重写Activity的 onSaveInstanceState() 和onRestoreInstanceState()方法.

      注意:在Activity的onCreate(Bundle savedInstanceState)方法里面,该方法的参数与onRestoreInstanceState(Bundle savedInstanceState)方法中的参数一致,因此在onCreate()方法中也能恢复缓存的数据。

    (2)onRestoreInstanceState()什么时候调用 

      onRestoreInstanceState()被调用的前提是,activity A"确实"被系统销毁了,这里特别注意是系统杀死不是人为编程finish等销毁的。而如果仅仅是停留在有这种可能性的情况下则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行 此也说明上二者,大多数情况下不成对被使用。

      onRestoreInstanceState()在onStart() 和 onPostCreate(Bundle)之间调用。

      再比如:如果activity B启动后位于activity A的前端,在某个时刻activity A 为系统回收资源的原因被杀掉了,A通过onSaveInstanceState将有机会保存其用户界面状态,使得将来用户返回到activity A时能通过onCreate(Bundle) 或者onRestoreInstanceState(Bundle)恢复界面的状态。

    8.下面我们编写测试 Activity生命周期方法onSaveInstanceState()

    (1)新建一个Android工程,创建MainActivity,SecondActivity,如下:

    MainActivity:

     1 package com.himi.saveactivitydemo;
     2 
     3 import android.app.Activity;
     4 import android.content.Intent;
     5 import android.os.Bundle;
     6 import android.view.View;
     7 
     8 public class MainActivity extends Activity {
     9     
    10     private int mCount = 0;  
    11     
    12     @Override
    13     protected void onCreate(Bundle savedInstanceState) {
    14         super.onCreate(savedInstanceState);
    15         if(savedInstanceState !=null) {
    16             int IntTest = savedInstanceState.getInt("IntTest");  
    17             String StrTest = savedInstanceState.getString("StrTest"); 
    18             
    19             System.out.println("---savedInstanceState+IntTest="+IntTest+"+StrTest="+StrTest);
    20         }
    21         setContentView(R.layout.activity_main);
    22         System.out.println("---MainActivity onCreate---");
    23         mCount++;
    24     }
    25     
    26     public void click(View view) {
    27         Intent intent = new Intent(this, SecondActivity.class);
    28         startActivity(intent);
    29     }
    30 
    31     
    32 
    33     @Override
    34     protected void onStart() {
    35         // TODO Auto-generated method stub
    36         super.onStart();
    37         System.out.println("---MainActivity onStart---");
    38     }
    39 
    40     @Override
    41     protected void onRestart() {
    42         // TODO Auto-generated method stub
    43         super.onRestart();
    44         System.out.println("---MainActivity onRestart---");
    45     }
    46 
    47     @Override
    48     protected void onResume() {
    49         // TODO Auto-generated method stub
    50         super.onResume();
    51         System.out.println("---MainActivity onResume---");
    52     }
    53 
    54     @Override
    55     protected void onSaveInstanceState(Bundle outState) {
    56         // TODO Auto-generated method stub
    57         outState.putInt("IntTest", mCount);  
    58         outState.putString("StrTest", "savedInstanceState test");  
    59         super.onSaveInstanceState(outState);
    60         System.out.println("---MainActivity onSaveInstanceState---");
    61     }
    62 
    63     @Override
    64     protected void onPause() {
    65         // TODO Auto-generated method stub
    66         super.onPause();
    67         System.out.println("---MainActivity onPause---");
    68     }
    69 
    70     @Override
    71     protected void onStop() {
    72         // TODO Auto-generated method stub
    73         super.onStop();
    74         System.out.println("---MainActivity onStop---");
    75     }
    76 
    77     @Override
    78     protected void onDestroy() {
    79         // TODO Auto-generated method stub
    80         super.onDestroy();
    81         System.out.println("---MainActivity onDestroy---");
    82     }
    83 
    84     
    85 }

    SecondActivity,如下:

     1 package com.himi.saveactivitydemo;
     2 
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 
     6 public class SecondActivity extends Activity {
     7 
     8     @Override
     9     protected void onCreate(Bundle savedInstanceState) {
    10         super.onCreate(savedInstanceState);
    11         setContentView(R.layout.second);
    12         System.out.println("---SecondActivity onCreate---");
    13     }
    14 
    15 
    16     @Override
    17     protected void onStart() {
    18         // TODO Auto-generated method stub
    19         super.onStart();
    20         System.out.println("---SecondActivity onStart---");
    21     }
    22 
    23     @Override
    24     protected void onRestart() {
    25         // TODO Auto-generated method stub
    26         super.onRestart();
    27         System.out.println("---SecondActivity onRestart---");
    28     }
    29 
    30     @Override
    31     protected void onResume() {
    32         // TODO Auto-generated method stub
    33         super.onResume();
    34         System.out.println("---SecondActivity onResume---");
    35     }
    36 
    37     //为了防止万一程序被销毁的风险,这个方法可以保证重要数据的正确性  
    38     //不写这个方法并不意味着一定出错,但是一旦遇到了一些非常奇怪的数据问题的时候  
    39     //可以看看是不是由于某些重要的数据没有保存,在程序被销毁时被重置  
    40     @Override
    41     protected void onSaveInstanceState(Bundle outState) {
    42         // TODO Auto-generated method stub
    43         super.onSaveInstanceState(outState);
    44         System.out.println("---SecondActivity onSaveInstanceState---");
    45     }
    46 
    47     @Override
    48     protected void onPause() {
    49         // TODO Auto-generated method stub
    50         super.onPause();
    51         System.out.println("---SecondActivity onPause---");
    52     }
    53 
    54     @Override
    55     protected void onStop() {
    56         // TODO Auto-generated method stub
    57         super.onStop();
    58         System.out.println("---SecondActivity onStop---");
    59     }
    60 
    61     @Override
    62     protected void onDestroy() {
    63         // TODO Auto-generated method stub
    64         super.onDestroy();
    65         System.out.println("---SecondActivity onDestroy---");
    66     }
    67 
    68     
    69 }

    (2)部署程序到手机上,同时观察Logcat,如下:

    接着我们点击上面的"跳转",如下:

    点击back键,如下:

    再次点击back键,如下:

    (3)退出上面的应用程序,重新运行,然后点击Home键,Logcat如下:

    点击程序,跳转到SecondActivity,再次点击Home键,Logcat如下:

    (4)退出应用程序,重新运行,然后竖屏显示转换为横屏显示,Logcat如下:

    9.下面我们编写测试 Activity生命周期方法 和 onRestoreInstanceState()

    修改之前上面的测试代码

    (1)修改后的MainActivity和SecondActivity,如下:

    MainActivity如下:

     1 package com.himi.saveactivitydemo;
     2 
     3 import android.app.Activity;
     4 import android.content.Intent;
     5 import android.os.Bundle;
     6 import android.view.View;
     7 
     8 public class MainActivity extends Activity {
     9     
    10     private String name;
    11     
    12     @Override
    13     protected void onCreate(Bundle savedInstanceState) {
    14         super.onCreate(savedInstanceState);
    15         if(savedInstanceState !=null) {
    16              
    17             String str= savedInstanceState.getString("name"); 
    18             
    19             System.out.println("---savedInstanceState store str is:---"+ str);
    20         }
    21         setContentView(R.layout.activity_main);
    22         System.out.println("---MainActivity onCreate---");
    23     
    24     }
    25     
    26     public void click(View view) {
    27         Intent intent = new Intent(this, SecondActivity.class);
    28         startActivity(intent);
    29     }
    30 
    31     
    32 
    33     @Override
    34     protected void onStart() {
    35         // TODO Auto-generated method stub
    36         super.onStart();
    37         System.out.println("---MainActivity onStart---");
    38     }
    39 
    40     @Override
    41     protected void onRestart() {
    42         // TODO Auto-generated method stub
    43         super.onRestart();
    44         System.out.println("---MainActivity onRestart---");
    45     }
    46 
    47     @Override
    48     protected void onResume() {
    49         // TODO Auto-generated method stub
    50         super.onResume();
    51         System.out.println("---MainActivity onResume---");
    52     }
    53 
    54     @Override
    55     protected void onSaveInstanceState(Bundle outState) {
    56         // TODO Auto-generated method stub
    57         outState.putString("name", "MainBoss");//被摧毁前缓存一些数据
    58         super.onSaveInstanceState(outState);
    59         System.out.println("---MainActivity onSaveInstanceState---");
    60     }
    61     
    62     @Override
    63     protected void onRestoreInstanceState(Bundle savedInstanceState) {
    64          name = savedInstanceState.getString("name"); //被重新创建后恢复缓存的数据
    65          super.onRestoreInstanceState(savedInstanceState);
    66          System.out.println("---MainActivity onRestoreInstanceState---");
    67     }
    68 
    69     @Override
    70     protected void onPause() {
    71         // TODO Auto-generated method stub
    72         super.onPause();
    73         System.out.println("---MainActivity onPause---");
    74     }
    75 
    76     @Override
    77     protected void onStop() {
    78         // TODO Auto-generated method stub
    79         super.onStop();
    80         System.out.println("---MainActivity onStop---");
    81     }
    82 
    83     @Override
    84     protected void onDestroy() {
    85         // TODO Auto-generated method stub
    86         super.onDestroy();
    87         System.out.println("---MainActivity onDestroy---");
    88     }
    89 
    90     
    91 }

    (2)部署程序到手机上,观察Logcat,如下:

    然后将MainActivity竖屏显示 转换为 横屏显示,观察Logcat如下:

  • 相关阅读:
    左偏树
    论在Windows下远程连接Ubuntu
    ZOJ 3711 Give Me Your Hand
    SGU 495. Kids and Prizes
    POJ 2151 Check the difficulty of problems
    CodeForces 148D. Bag of mice
    HDU 3631 Shortest Path
    HDU 1869 六度分离
    HDU 2544 最短路
    HDU 3584 Cube
  • 原文地址:https://www.cnblogs.com/hebao0514/p/4737887.html
Copyright © 2020-2023  润新知