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

Android Activity为什么要细化出onCreate、onStart、onResume、onPause、onStop、onDesdroy这么多方法让应用去重载?最近在研究Activity的启动流程,老罗的blog在看,也找了其它资料学习,也跟过Android4.3的源码,在跟代码的过程中,突然想到下面的这个问题:  AndroidActivity为什么要细化出onCreate、onStart、onResume、onPause、onStop、onDesdroy这么多方法让应用去重载?网上太多根据Android开发规范翻译转载的内容,都不是我想要的答案,那就自己分析下

大家好,又见面了,我是你们的朋友全栈君。

原创链接:http://blog.csdn.net/zhao_3546/article/details/12843477,转载请注明,谢谢。

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

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

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

网上太多根据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()操作,即使这里面有些比较耗时的操作,也没有关系,这是在后台执行所以也不影响用户的体验。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/137804.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • eclipse中通过svn检出项目代码

    eclipse中通过svn检出项目代码eclipse中通过svn检出项目代码

    2022年4月24日
    78
  • 数据库表结构设计方法及原则「建议收藏」

    数据库表结构设计方法及原则「建议收藏」http://www.cnblogs.com/RunForLove/p/5693986.html  数据库设计的三大范式:为了建立冗余较小、结构合理的数据库,设计数据库时必须遵循一定的规则。在关系型数据库中这种规则就称为范式。范式是符合某一种设计要求的总结。要想设计一个结构合理的关系型数据库,必须满足一定的范式。  在实际开发中最为常见的设计范式有三个:第一范式是最基本的范式。如果数据

    2025年11月7日
    1
  • df.fillna()_python的dropna

    df.fillna()_python的dropnaimportpandasaspdimportnumpyasnpdf=pd.DataFrame([[1,2,3],[np.nan,np.nan,2],[np.nan,np.nan,np.nan],[8,8,np.nan]])dfdf.fillna({0:10,1:11,2:22})有人问,列中以为有了nan,所以…

    2022年8月12日
    11
  • 网络请求发生错误: Unsupported Media Type

    网络请求发生错误: Unsupported Media Type环信获取token时,请求失败UnsupportedMediaTypexutls发送json数据

    2022年5月15日
    40
  • ViewStub总结

    ViewStub总结ViewStub是一个不可见的,大小为0的View,最佳用途就是实现View的延迟加载,避免资源浪费,在需要的时候才加载View;其特性如下:1、调用其inflate()的时候,其布局属性android:layout=”@layout/布局”将会替换这个ViewStub标签,这个时候我们使用findViewById将获取这个ViewStub对象为空,所以是可以被替换这一点的;2、infla

    2022年6月28日
    25
  • Python画图显示中文

    Python画图显示中文matplotlib作图时默认设置下为英文,无法显示中文,只需要添加下面两行代码即可plt.rcParams[‘font.sans-serif’]=[‘SimHei’]plt.rcParams[‘axes.unicode_minus’]=FalseExampleimportmatplotlib.pyplotaspltfromnumpy.randomimportmul…

    2022年6月1日
    37

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号