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:

 package com.himi.saveactivitydemo;

 import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View; public class MainActivity extends Activity { private int mCount = 0; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState !=null) {
int IntTest = savedInstanceState.getInt("IntTest");
String StrTest = savedInstanceState.getString("StrTest"); System.out.println("---savedInstanceState+IntTest="+IntTest+"+StrTest="+StrTest);
}
setContentView(R.layout.activity_main);
System.out.println("---MainActivity onCreate---");
mCount++;
} public void click(View view) {
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
} @Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
System.out.println("---MainActivity onStart---");
} @Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
System.out.println("---MainActivity onRestart---");
} @Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
System.out.println("---MainActivity onResume---");
} @Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
outState.putInt("IntTest", mCount);
outState.putString("StrTest", "savedInstanceState test");
super.onSaveInstanceState(outState);
System.out.println("---MainActivity onSaveInstanceState---");
} @Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
System.out.println("---MainActivity onPause---");
} @Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
System.out.println("---MainActivity onStop---");
} @Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
System.out.println("---MainActivity onDestroy---");
} }

SecondActivity,如下:

 package com.himi.saveactivitydemo;

 import android.app.Activity;
import android.os.Bundle; public class SecondActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
System.out.println("---SecondActivity onCreate---");
} @Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
System.out.println("---SecondActivity onStart---");
} @Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
System.out.println("---SecondActivity onRestart---");
} @Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
System.out.println("---SecondActivity onResume---");
} //为了防止万一程序被销毁的风险,这个方法可以保证重要数据的正确性
//不写这个方法并不意味着一定出错,但是一旦遇到了一些非常奇怪的数据问题的时候
//可以看看是不是由于某些重要的数据没有保存,在程序被销毁时被重置
@Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
System.out.println("---SecondActivity onSaveInstanceState---");
} @Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
System.out.println("---SecondActivity onPause---");
} @Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
System.out.println("---SecondActivity onStop---");
} @Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
System.out.println("---SecondActivity onDestroy---");
} }

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

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

点击back键,如下:

再次点击back键,如下:

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

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

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

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

修改之前上面的测试代码

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

MainActivity如下:

 package com.himi.saveactivitydemo;

 import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View; public class MainActivity extends Activity { private String name; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState !=null) { String str= savedInstanceState.getString("name"); System.out.println("---savedInstanceState store str is:---"+ str);
}
setContentView(R.layout.activity_main);
System.out.println("---MainActivity onCreate---"); } public void click(View view) {
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
} @Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
System.out.println("---MainActivity onStart---");
} @Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
System.out.println("---MainActivity onRestart---");
} @Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
System.out.println("---MainActivity onResume---");
} @Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
outState.putString("name", "MainBoss");//被摧毁前缓存一些数据
super.onSaveInstanceState(outState);
System.out.println("---MainActivity onSaveInstanceState---");
} @Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
name = savedInstanceState.getString("name"); //被重新创建后恢复缓存的数据
super.onRestoreInstanceState(savedInstanceState);
System.out.println("---MainActivity onRestoreInstanceState---");
} @Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
System.out.println("---MainActivity onPause---");
} @Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
System.out.println("---MainActivity onStop---");
} @Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
System.out.println("---MainActivity onDestroy---");
} }

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

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

Android(java)学习笔记113:Activity的生命周期的更多相关文章

  1. Android开发学习之路--Activity之生命周期

    其实这篇文章应该要在介绍Activity的时候写的,不过那个时候还不怎么熟悉Activity,还是在这里详细介绍下好了.还是参考下官方文档的图吧: 从上面的流程,我们可以看出首先就是打开APP,开始执 ...

  2. Java学习笔记之——线程的生命周期、线程同步

    一. 线程的生命周期 新建(new Thrad):创建线程后,可以设置各个属性值,即启动前 设置 就绪(Runnable):已经启动,等待CPU调动 运行(Running):正在被CPU调度 阻塞(B ...

  3. Android SDK上手指南:Activity与生命周期

    Android SDK上手指南:Activity与生命周期 2013-12-26 15:26 核子可乐译 51CTO 字号:T | T Activity生命周期并不仅仅在用户运行应用程序之后才开始生效 ...

  4. android学习四(Activity的生命周期)

    要学好活动(Activity).就必需要了解android中Activity的声明周期.灵活的使用生命周期.能够开发出更好的程序,在android中是使用任务来管理活动的,一个任务就是一组存放在栈里的 ...

  5. Android开发艺术探索读书笔记——01 Activity的生命周期

    http://www.cnblogs.com/csonezp/p/5121142.html 新买了一本书,<Android开发艺术探索>.这本书算是一本进阶书籍,适合有一定安卓开发基础,做 ...

  6. android开发艺术探索学习 之 结合Activity的生命周期了解Activity的LaunchMode

    转载请标明出处: http://blog.csdn.net/lxk_1993/article/details/50749728 本文出自:[lxk_1993的博客]: 首先还是先介绍下Activity ...

  7. Android开发艺术1之Activity的生命周期

    作为<Android开发艺术探索>这本书的第一篇博客,我就多说几句.本系列博客旨在对书中相关内容进行解读,简化,提供一个入门到提高的流程.不敢说书评,也不能说教程,只希望对有些人有帮助就好 ...

  8. Android 横屏切换竖屏Activity的生命周期(转)

    曾经遇到过一个面试题,让你写出横屏切换竖屏Activity的生命周期.现在给大家分析一下他切换时具体的生命周期是怎么样的:  1.新建一个Activity,并把各个生命周期打印出来  2.运行Acti ...

  9. Android(java)学习笔记171:Service生命周期

    1.Service的生命周期         Android中的Service(服务)与Activity不同,它是不能和用户交互,不能自己启动的,运行在后台的程序,如果我们退出应用的时候,Servic ...

  10. Android(java)学习笔记114:Service生命周期

    1.Service的生命周期         Android中的Service(服务)与Activity不同,它是不能和用户交互,不能自己启动的,运行在后台的程序,如果我们退出应用的时候,Servic ...

随机推荐

  1. The web.config file for this project is missing the required DirectRequestModule.

    The web.config file for this project is missing the required DirectRequestModule.   将应用程序集的模式由集成改为经典 ...

  2. mui 关闭当前窗口

    在提交表单的时候,我们都需要关闭表单.需要关闭当前打开的窗口. bit.alert('提交成功' + (result.category.needAudit ? ",请耐心等待管理员审核信息后 ...

  3. Git 时光穿梭鸡 撤销修改

    工作区内容修改了, 但是并未add到暂存区, 想 回退到上一个版本 在readme.txt中添加了一行: Git is a distributed version control system. Gi ...

  4. PyCharm中导入第三方包

    在Windows中的PyCharm中导入模块的方法 1.在file-->setting-->project interpreter中 2,点击右上角加号,搜索要添加的第三方库的名称,得到后 ...

  5. 安装wepack

    安装webpack之前要安装node.js 1.安装webpack运行 npm install webpack -g 和npm install webpack-cli -g npm install w ...

  6. javascript的程序控制结构及语句------(2)循环控制语句、跳转语句、对话框

    一.循环控制语句 循环语句主要就是在满足条件的情况下反复执行某一个操作,循环控制语句主要包括while语句.do...while语句 和for语句. 1.While语句 语法: While(条件表达式 ...

  7. python 之 匿名函数

    5.14 匿名函数 lambda x , y : x+y 1 匿名的目的就是要没有名字,给匿名函数赋给一个名字是没有意义的 2 匿名函数的参数规则.作用域关系与有名函数是一样的 3 匿名函数的函数体通 ...

  8. NOIp知识集合 By cellur925

    基本算法 快速幂 ll ksm(ll a,ll b) { ll ans=; while(b) { ) ans=ans*a%p; b>>=; a=a*a%p; } return ans; } ...

  9. oracle merge 目标表以及源表存在重复列的问题(转)

    SQL> select * from t_source;                                                                      ...

  10. 洛谷 P1434 [SHOI2002]滑雪 解题报告

    这题方法有很多, 这里介绍2种: 方法1 很容易想到搜索, bfs或dfs应该都可以, 就不放代码了: 方法2 这题还可以用 dp 来做. 做法:先将每个点按照高度从小到大排序,因为大的点只能向小的点 ...