zoukankan      html  css  js  c++  java
  • 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如下:

  • 相关阅读:
    ACM学习
    吴翼大神
    心急的C小加(两种解法)
    万圣节派对(水题)
    poj 1163 The Triangle
    POJ 1088滑雪
    1690 开关灯
    908. 校园网
    STL之stack栈
    1163 访问艺术馆
  • 原文地址:https://www.cnblogs.com/hebao0514/p/4737887.html
Copyright © 2011-2022 走看看