概述
最近在研究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.
staticfinalintPAUSE_TIMEOUT =500;// 定义在ActivityStack.java中
AActivity中比较消耗资源的部分关闭后,再切换到BActivity中执行BActivity的初始化,显示BActivity中的View。
当BActivity已经执行显示出来了,用户可以交互,后台再去执行AActivity的onStop()操作,即使这里面有些比较耗时的操作,也没有关系,这是在后台执行所以也不影响用户的体验。
最后
以上就是孝顺夕阳为你收集整理的android activity onstart直接到onstop,Android Activity细化出onCreate、onStart、onResume、onPause、onStop、onDesd...的全部内容,希望文章能够帮你解决android activity onstart直接到onstop,Android Activity细化出onCreate、onStart、onResume、onPause、onStop、onDesd...所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复