Android Activity为什么要细化出onCreate、onStart、onResume、onPause、onStop、onDesdroy这么多方法让应用去重载?

原文:http://www.xuebuyuan.com/1608083.html

最近在研究Activity的启动流程,老罗的blog在看,也找了其它资料学习,也跟过Android4.3的源码,

在跟代码的过程中,突然想到下面的这个问题:

网上太多根据Android开发规范翻译转载的内容,都不是我想要的答案,那就自己分析下。

如下是一段典型的Activity间切换的日志,从AActivity切换到BActivity:

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

当触发从AActivity切换到BActivity时的日志如下:

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

先AActivity的onPause()被调用,然后是BActivity的初始化流程(onCreate() --> onStart() --> onResume()),再然后是AActivity的onStop()被调用。

有点意思,为什么不是先AActivity的onPause()、onStop()被调用,然后再BActivity的初始化流程(onCreate() --> onStart() --> onResume())?

或者又为什么不是先BActivity的初始化流程(onCreate() --> onStart() --> onResume()),再AActivity的onPause()、onStop()被调用?

如下是Activity的几个关键方法的注释:

void android.app.Activity.onCreate(Bundle savedInstanceState)
Called when the activity is starting. This is where most initialization should go: calling setContentView(int) to inflate the activity‘s UI, using findViewById to programmatically interact with widgets in the UI, calling managedQuery(android.net.Uri, String[],
String, String[], String) to retrieve cursors for data being displayed, etc. 
You can call finish from within this function, in which case onDestroy() will be immediately called without any of the rest of the activity lifecycle (onStart, onResume, onPause, etc) executing.

void android.app.Activity.onStart()

Called after onCreate — or after onRestart when the activity had been stopped, but is now again being displayed to the user. It will be followed by onResume.

void android.app.Activity.onResume()

Called after onRestoreInstanceState, onRestart, or onPause, for your activity to start interacting with the user. This is a good place to begin animations, open exclusive-access devices (such as the camera), etc.

Keep in mind that onResume is not the best indicator that your activity is visible to the user; a system window such as the keyguard may be in front. Use onWindowFocusChanged to know for certain that your activity is visible to the user (for example, to
resume a game).

void android.app.Activity.onPause()

Called as part of the activity lifecycle when an activity is going into the background, but has not (yet) been killed. The counterpart to onResume.

When activity B is launched in front of activity A, this callback will be invoked on A. B will not be created until A‘s onPause returns, so be sure to not do anything lengthy here.

This callback is mostly used for saving any persistent state the activity is editing, to present a "edit in place" model to the user and making sure nothing is lost if there are not enough resources to start the new activity without first killing this one.
This is also a good place to do things like stop animations and other things that consume a noticeable amount of CPU in order to make the switch to the next activity as fast as possible, or to close resources that are exclusive access such as the camera.

In situations where the system needs more memory it may kill paused processes to reclaim resources. Because of this, you should be sure that all of your state is saved by the time you return from this function. In general onSaveInstanceState is used to save
per-instance state in the activity and this method is used to store global persistent data (in content providers, files, etc.)

After receiving this call you will usually receive a following call to onStop (after the next activity has been resumed and displayed), however in some cases there will be a direct call back to onResume without going through the stopped state.

void android.app.Activity.onStop()

Called when you are no longer visible to the user. You will next receive either onRestart, onDestroy, or nothing, depending on later user activity.

Note that this method may never be called, in low memory situations where the system does not have enough memory to keep your activity‘s process running after its onPause method is called.

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

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

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

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

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

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

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

1、 在 onResume() 的注释中,建议是在onResume()中打开独占设备(比如相机),与onResume()对应的是onPause(),所以所有的去初始化操作放在onStop()中执行,可能会引出新的问题;

2、onStop() 的注释中明确地写了,在内存不足而导致系统无法保留此进程的情况下,onStop() 可能都不会被执行。

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

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

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

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

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

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

从AActivity切换到BActivity的日志如下:

10-17 20:54:46.997: I/com.example.servicetest.AActivity(5817): onPause() 1166919192 taskID=66
10-17 20:54:47.021: I/com.example.servicetest.BActivity(5817): onCreate() 1166971824 taskID=66
10-17 20:54:47.028: I/com.example.servicetest.BActivity(5817): onStart() 1166971824 taskID=66
10-17 20:54:47.028: I/com.example.servicetest.BActivity(5817): onResume() 1166971824 taskID=66
10-17 20:54:47.099: I/com.example.servicetest.AActivity(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中

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

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

时间: 2024-12-18 18:02:24

Android Activity为什么要细化出onCreate、onStart、onResume、onPause、onStop、onDesdroy这么多方法让应用去重载?的相关文章

Android onCreate onStart onResume onPause onStop onDestroy

Android中一个Activity一般都需要实现六个函数: onCreate(), onStart(), onResume(),onPause(),onStop(),onDestroy(). onCreate函数:注册你要用到的变量,比如说service,receiver,这些变量是无论你的Activity是在前台还是在后台都能够被响应到的,然后调用上面那个用来初始化的函数初始化布局信息. onStart函数:注册一些变量.这些变量必须在Android Activity类在前台的时候才能够被响

android知activity生命周期--不要只用onCreate方法

应该知道:Android Activity细化出onCreate.onStart.onResume.onPause.onStop.onDesdroy这6个方法让应用去重载,其中要问为什么?点击查看Android Activity为什么要细化出onCreate.onStart.onResume? 这里只说明这6个函数在什么时候情况下被调用以及调用的顺序: 一个Activity启动正常启动:onCreate()->onStart()->onResume(); 一个Activity启动正常退出:on

Android Activity生命周期的几个问题

每一个Android开发者都应该知道,android系统有四个重要的基本组件,即Activity(活动).Service(服务).Broadcast Receive(广播接收器)和Content Provider(内容提供器),其中,Activity是最重要的组件,打开你手机上的APP,你眼睛所能看到的都是Activity,下面将会介绍关于Activity生命周期的几个问题. 1 Activity生命周期的8个回调函数 下图是Activity的生命周期图,相信许多人都看过不止一次,但有的人是看到

Android Activity生命周期及启动模式

曾经搞过许多东西,再熟练的东西一段时间没有碰都会生疏或忘记.后来体会到写成文档记录下来的重要性,但有些word或ppt记录下来的东西随着时间流逝会丢失,或者不愿去看.或许保存成博客的形式,会是更好的选择,勉励自己. Activiy是Android开发中最常用最常见的组件,是Android开发人员开始学习首先接触的组件,也是大部分人建立一个工程后,首先要处理的可能就是Activity.这么重要.常用.简单.易上手的组件,牢固掌握其基础知识,对于开发人员是非常重要的.本文会首先解释其基本概念,对于其

Android——Activity中的六个主要函数

Android Activity中的六个主要函数 Android中一个Activity一般都需要实现六个函数: onCreate(), onStart(), onResume(),onPause(),onStop(),onDestroy(). onCreate函数:注册你要用到的变量,比如说service,receiver,这些变量是无论你的Activity是在前台还是在后台都能够被响应到的,然后调用上面那个用来初始化的函数初始化布局信息. onStart函数:注册一些变量.这些变量必须在And

从零开始学android<ACtivity的生命周期.三十九.>

意图是指两个UI主界面的转换,要想了解意图就必须学习ACtivity的生命周期 默认在UI界面显示的为运行为运行状态,而在后台的为onPause方法 主线: OnCreate()--> OnStart() --> OnResume() -->OnPause()-->OnStop ()-->OnDestroy() 副线: OnCreate()--> OnStart() --> OnResume() -->OnPause()-->OnStop ()--&g

android Activity生命周期的例子

package com.example.yanlei.yl2; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnKeyListener; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.ap

Android Activity Intent

首先定义一个LifeCycleActivity的类,继承Activity,重写onCreat() onStart()  onResume()  onPause()  onStop()  onDestroy() 1 import android.app.Activity; 2 import android.os.Bundle; 3 import android.util.Log; 4 5 public class LifeCycleActivity extends Activity{ 6 7 @O

Android Activity类讲解(一)

--by CY[[email protected]] 1.protected void onCreate(Bundle savedInstanceState) { throw new RuntimeException("Stub!"); } 当创建一个Activity时,系统会自动调用onCreate方法来完成创建工作.该创建工作包括布局,监听器的绑定等. 首先说一下Bundle 这个类,Bundle是一个键值对,跟Map类似,两个Activity之间的通信可以用Bundle类来实现.