很高兴碰见你~ 欢迎阅读个人文章。java
关于Activity生命周期的文章,网络上真的不少,有不少的博客也都讲得至关不错,可见Activity的重要性是很是高的。事实上,我猜想每一个android开发者接触的第一个android组件都是Activity。咱们重新建第一个Activity开始,运行了代码,看到模拟机上显示了一个MainActivity标题和一行HolleWorld,今后打开Android世界的大门。android
本篇文章讲解的重点是Activity的生命周期,在文章的最后也会涉及Activity的设计。不一样于其余的博客设计,文章采用系统化的讲解,关于Activity生命周期的相关知识基本都会涉及到。git
那么,咱们开始吧。数据库
Activity是一个很重要、很复杂的组件,他的启动不像咱们平时直接new一个对象就完事了,他须要经历一系列的初始化。例如"刚建立状态",“后台状态”,“可见状态”等等。当咱们在界面之间进行切换的时候,activity也会在多种状态之间进行切换,例如可见或者不可见状态、前台或者后台状态。当Activity在不一样的状态之间切换时,会回调不一样的生命周期方法。咱们能够重写这一些方法,当进入不一样的状态的时候,执行对应的逻辑。设计模式
在ActivityLifecycleItem`抽象类中定义了9种状态。这个抽象类有不少的子类,是AMS管理Activity生命周期的事务类。(其实就像一个圣旨,AMS丢给应用程序,那么应用程序就必须执行这个圣旨)Activity主要使用其中6个(这里的6个是笔者在源码中明确看到调用setState来设置状态,其余的三种并未看到调用setState方法来设置状态,因此这里主要讲这6种),以下:api
// Activity刚被建立时 public static final int ON_CREATE = 1; // 执行完转到前台的最后准备工做 public static final int ON_START = 2; // 执行完即将与用户交互的最后准备工做 // 此时该activity位于前台 public static final int ON_RESUME = 3; // 用户离开,activity进入后台 public static final int ON_PAUSE = 4; // activity不可见 public static final int ON_STOP = 5; // 执行完被销毁前最后的准备工做 public static final int ON_DESTROY = 6;
状态之间的跳转不是随意的,例如不能从ON_CREATE
直接跳转到ON_PAUSE
状态,状态之间的跳转收到AMS的管理。当Activity在这些状态之间切换的时候,就会回调对应的生命周期。这里的状态看着很很差理解,笔者画了个图帮助理解一下:微信
这里按照「可交互」「可见」「可存在」三个维度来区分Activity的生命状态。可交互则为是否能够与用户操做;可见则为是否显示在屏幕上;可存在,则为该activity是否被系统杀死或者调用了finish方法。箭头的上方为进入对应状态会调用的方法。这里就先不展开讲每一个状态之间的切换,主要是让读者能够更好地理解activity的状态与状态切换。网络
注意,这里使用的三个维度并非很是严谨的,是结合整体的显示规则来进行区分的。app
在谷歌的官方文档中对于
onStart
方法是这样描述的:onStart()
调用使 Activity 对用户可见,由于应用会为 Activity 进入前台并支持互动作准备。这也符合咱们上面的维度的区分。而当activity进入ON_PAUSE状态的时候,Activity是可能依旧可见的,可是不可交互。如操做另外一个应用的悬浮窗口的时候,当前应用的activity会进入ON_PAUSE状态。ide可是!在activity启动的流程中,直到onResume方法被调用,界面依旧是不可见的。这点在后面的源码分析再详细解释。因此这里的状态区分维度,仅仅只是整体上的一种区分,能够这么认为,但细节上并非很是严谨的。须要读者注意一下。
生命周期的一个重要做用就是让activity在不一样状态之间切换的时候,能够执行对应的逻辑。举个栗子。咱们在界面A使用了相机资源,当咱们切换到下个界面B的时候,那么界面A就必须释放相机资源,这样才不会致使界面B没法使用相机;而当咱们切回界面A的时候,又但愿界面A继续保持拥有相机资源的状态;那么咱们就须要在界面不可见的时候释放相机资源,而在界面恢复的时候再次获取相机资源。每一个Activity通常状况下能够认为是一个界面或者说,一个屏幕。当咱们在界面之间进行导航切换的时候,其实就是在切换Activity。当界面在不一样状态之间进行切换的时候,也就是Activity状态的切换,就会回调activity相关的方法。例如当界面不可见的时候会回调onStop
方法,恢复的时候会回调onReStart
方法等。
在合适的生命周期作合适的工做会让app变得更加有鲁棒性。避免当用户跳转别的app的时候发生崩溃、内存泄露、当用户切回来的时候失去进度、当用户旋转屏幕的时候失去进度或者崩溃等等。这些都须要咱们对生命周期有必定的认知,才能在具体的场景下作出最正确的选择。
这一部分概述并无展开讲生命周期,而是须要重点理解状态与状态之间的切换,生命周期的回调就发生在不一样的状态之间的切换。咱们学习生命周期的一个重要目的就是可以在对应的业务场景下作合适的工做,例如资源的申请、释放、存储、恢复,让app更加具备鲁棒性。
关于Activity重要的生命周期回调方法谷歌官方有了一张很是重要的流程图,能够说是人人皆知。我在这张图上加上了一些经常使用的回调方法。这些方法严格上并不算Activity的生命周期,由于并无涉及到状态的切换,但却在Activity的整个生命历程中发挥了很是大的做用,也是很重要的回调方法。方法不少,咱们先看图,再一个个地解释。看具体方法解释的时候必定要结合下面这张图以及上一部分概述的图一块儿理解。
首先咱们先看到最重要的七个生命周期,这七个生命周期是严格意义上的生命周期,他符合状态切换这个关键定义。这部份内容建议结合概述部分的图一块儿理解。(onRestart并不涉及状态变换,但由于执行完他以后会立刻执行onStart,因此也放在一块儿讲)
onCreate:当Activity建立实例完成,并调用attach方法赋值PhoneWindow、ContextImpl等属性以后,调用此方法。该方法在整个Activity生命周期内只会调用一次。调用该方法后Activity进入ON_CREATE
状态。
该方法是咱们使用最频繁的一个回调方法。
咱们须要在这个方法中初始化基础组件和视图。如viewmodel,textview。同时必须在该方法中调用setContentView来给activity设置布局。
这个方法接收一个参数,该参数保留以前状态的数据。若是是第一次启动,则该参数为空。该参数来自onSaveInstanceState存储的数据。只有当activity暂时销毁而且预期必定会被从新建立的时候才会被回调,如屏幕旋转、后台应用被销毁等
onStart:当Activity准备进入前台时会调用此方法。调用后Activity会进入ON_START
状态。
要注意理解这里的前台的意思。虽然谷歌文档中表示调用该方法以后activity可见,以下图:
![]()
可是咱们前面讲到,前台并不意味着Activity可见,只是表示activity处于活跃状态。这也是谷歌文档里让我比较迷惑的地方之一。(事实上谷歌文档有挺多地方写的缺少严谨,可能考虑到易懂性,就牺牲了一点严谨性吧)。
前台activity通常只有一个,因此这也意味着其余的activity都进入后台了。这里的先后台须要结合activity返回栈来理解,后续笔者再写一篇关于返回栈的。
这个方法通常用于从别的activity切回来本activity的时候调用。
onResume:当Activity准备与用户交互的时候调用。调用以后Activity进入ON_RESUME
状态。
注意,这个方法一直被认为是activity必定可见,且准备好与用户交互的状态。但事实并不一直是这样。若是在
onReume
方法中弹出popupWindow你会收获一个异常:token is null
,表示界面尚没有被添加到屏幕上。可是,这种状况只出如今第一次启动activity的时候。当activity启动后decorview就已经拥有token了,再次在
onReume
方法中弹出popupWindow就不会出现问题了。所以,在onResume调用的时候activity是否可见要区分是不是第一次建立activity。
onStart方法是后台与前台的区分,而这个方法是是否可交互的区分。使用场景最可能是在当弹出别的activity的窗口时,原activity就会进入
ON_PAUSE
状态,可是仍然可见;当再次回到原activity的时候,就会回调onResume方法了。
onPause:当前activity窗口失去焦点的时候,会调用此方法。调用后activity进入ON_PAUSE
状态,并进入后台。
这个方法通常在另外一个activity要进入前台前被调用。只有当前activity进入后台,其余的activity才能进入前台。因此,该方法不能作重量级的操做,否则则会引用界面切换卡顿。
通常的使用场景为界面进入后台时的轻量级资源释放。
最好理解这个状态就是弹出另外一个activity的窗口的时候。由于前台activity只能有一个,因此当前可交互的activity变成另外一个activity后,原activity就必须调用onPause方法进入
ON_PAUSE
状态;可是!!仍然是可见的,只是没法进行交互。这里也能够更好地体会前台可交互与可见性的区别。
onStop:当activity不可见的时候进行调用。调用后activity进入ON_STOP
状态。
这里的不可见是严谨意义上的不可见。
当activity不可交互时会回调onPause方法并进入
ON_PAUSE
状态。但若是进入的是另外一个全屏的activity而不是小窗口,那么当新的activity界面显示出来的时候,原Activity才会进入ON_STOP
状态,并回调onStop方法。同时,activity第一建立的时候,界面是在onResume方法以后才显示出来,因此onStop方法会在新activity的onResume方法回调以后再被回调。注意,被启动的activity并不会等待onStop执行完毕以后再显示。于是若是onStop方法里作一些比较耗时的操做也不会致使被启动的activity启动延迟。
onStop方法的目的就是作资源释放操做。由于是在另外一个activity显示以后再被回调,因此这里能够作一些相对重量级的资源释放操做,如中断网络请求、断开数据库链接、释放相机资源等。
若是一个应用的所有activity都处于
ON_STOP
状态,那么这个应用是颇有可能被系统杀死的。而若是一个ON_STOP
状态的activity被系统回收的话,系统会保留该activity中view的相关信息到bundle中,下一次恢复的时候,能够在onCreate或者onRestoreInstanceState中进行恢复。
onRestart :当从另外一个activity切回到该activity的时候会调用。调用该方法后会当即调用onStart方法,以后activity进入ON_START
状态。
这个方法通常在activity从
ON_STOP
状态被从新启动的时候会调用。执行该方法后会当即执行onStart方法,而后Activity进入ON_START
状态,进入前台。
onDestroy:当activity被系统杀死或者调用finish方法以后,会回调该方法。调用该方法以后activity进入ON_DESTROY
状态。
这个方法是activity在被销毁前回调的最后一个方法。咱们须要在这个方法中释放全部的资源,防止形成内存泄漏问题。
回调该方法后的activity就等待被系统回收了。若是再次打开该activity须要从onCreate开始执行,从新建立activity。
那到这里七个最关键的生命周期方法就讲完了。须要读者注意的是,在概述一图中,咱们使用了三个维度来进行区分不一样类型的状态,可是很明显,同一类型的状态并非等价的。如ON_START
状态表示activity进入前台,而ON_PAUSE
状态却表示activity进入后台。这可能也是为何谷歌要区分出on_start和on_pause两个状态,他们表明并非一致的状态。
这七个生命周期回调方法是最重要的七个生命周期回调方法,须要读者好好理解每一个回调方法设计到的activity的状态转换。而理解了状态转换后,也就能够写出更增强壮的代码了。
这个方法也很常见,他须要结合startActivityForResult
一块儿使用。
使用的场景是:启动一个activity,并指望在该activity结束的时候返回数据。
当启动的activity结束的时候,返回原activity,原activity就会回调onActivityResult方法了。该方法执行在其余全部的生命周期方法前。关于onActivityResult如何使用这里就不展开了,咱们主要介绍生命周期。
这两个方法,主要用于在Activity被意外杀死的状况下进行界面数据存储与恢复。什么叫意外杀死呢?
若是你主动点击返回键、调用finish方法、从多任务列表清除后台应用等等,这些操做表示用户想要完整得退出activity,那么就没有必要保留界面数据了,因此也不会调用这两个方法。而当应用被系统意外杀死,或者系统配置更改致使的activity销毁,这个时候当用户返回activity时,指望界面的数据还在,则会经过回调onSaveInstanceState方法来保存界面数据,而在activity从新建立并运行的时候调用onRestoreInstanceState方法来恢复数据。事实上,onRestoreInstanceState方法的参数和onCreate方法的参数是一致的,只是他们两个方法回调的时机不一样。所以,判断是否执行的关键因素就是用户是否指望返回该activity时界面数据仍然存在。
这里须要注意几个点:
不一样android版本下,onSaveInstanceState方法的调用时机是不一样的。目前笔者的源码是api30,在官方注释中能够看到这么一句话:
/*If called, this method will occur after {@link #onStop} for applications * targeting platforms starting with {@link android.os.Build.VERSION_CODES#P}. * For applications targeting earlier platform versions this method will occur * before {@link #onStop} and there are no guarantees about whether it will * occur before or after {@link #onPause}. */
翻译过来意思就是,在api28及以上版本onSaveInstanceState是在onStop以后调用的,可是在低版本中,他是在onStop以前被调用的,且与onPause之间的顺序是不肯定的。
当activity进入后台的时候,onSaveInstanceState方法则会被调用,而不是异常状况下才会调用onSaveInstanceState方法,由于并不肯定在后台时,activity是否会被系统杀死,因此以最保险的方法,先保存数据。当确实是由于异常状况被杀死时,返回activity用户指望界面须要恢复数据,才会调用onRestoreInstanceState来恢复数据。可是,activity直接按返回键或者调用finish方法直接结束Activity的时候,是不会回调onSaveInstanceState方法,由于很是明确下一次返回该activity用户指望的是一个干净界面的新activity。
onSaveInstanceState不能作重量级的数据存储。onSaveInstanceState存储数据的原理是把数据序列化到磁盘中,若是存储的数据过于庞大,会致使界面卡顿,掉帧等状况出现。
正常状况下,每一个view都会重写这两个方法,当activity的这两个方法被调用的时候,会向上委托window去调用顶层viewGroup的这两个方法;而viewGroup会递归调用子view的onSaveInstanceState/onRestoreInstanceState方法,这样全部的view状态就都被恢复了。
关于界面数据恢复这里也不展开细讲了,有兴趣的读者能够自行深刻研究。
这个方法其实和onPostResume是同样的,一样的还有onContextChange方法。这三个方法都是不经常使用的,这里也点出其中一个来统一讲一下。
onPostCreate方法发生在onRestoreInstanceState以后,onResume以前,他表明着界面数据已经彻底恢复,就差显示出来与用户交互了。在onStart方法被调用时这些操做还没有完成。
onPostResume是在Resume方法被彻底执行以后的回调。
onContentChange是在setContentView以后的回调。
这些方法都不经常使用,仅作了解。若是真的遇到了具体的业务需求,也能够拿出来用一下。
这个方法涉及到的场景也是重复启动,可是与onRestart方法被调用的场景是不一样的。
咱们知道activity是有多种启动模式的,其中singleInstance、singleTop、singleTask都保证了在必定状况下的单例状态。如singleTop,若是咱们启动一个正处于栈顶且启动模式为singleTop的activity,那么他并不会在建立一个activity实例,而是会回调该activity的onNewIntent方法。该方法接收一个intent参数,该参数就是新的启动Intent实例。
其余的状况如singleTask、singleInstance,当遇到这种强制单例状况时,都会回调onNewIntent方法。关于启动模式这里也不展开,后续笔者可能会再出一期文章讲启动模式。
这一部分主要是讲解在一些场景下,生命周期方法的回调顺序。对于当个Activity而言,上述流程图已经展现了各类状况下的生命周期回调顺序了。可是,当启动另外一个activity的时候,究竟是onStop先执行,仍是被启动的onStart先执行呢?这些就变得比较难以肯定。
验证生命周期回调顺序最好的方法就是写demo,经过日志打印,能够很明显地观察到生命周期的回调顺序。固然,查看源码也是一个不错的方法,可是须要对系统源码有必定的认识,咱们仍是选择简单粗暴的方法。
onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy
这种状况的生命周期比较好理解,就是常规的启动与结束,也不会涉及到第二个activity。最后看日志打印:
Activity1:onPause
Activity2:onCreate -> onStart -> onResume
Activity1:onStop
当切换到另外一个activity的时候,本activity会先调用onPause方法,进入后台;被启动的activity依次调用三个回调方法后准备与用户交互;这时原activity再调用onStop方法变得不可见,最后被启动的activity才会显示出来。
理解这个生命周期顺序只须要记住两个点:先后台、是否可见。onPause调用以后,activity会进入后台。而前台交互的activity只能有一个,因此原activity必须先进入后台后,目标activity才能启动并进入前台。onStop调用以后activity变得不可见,于是只有在目标activity即将要与用户交互的时候,须要进行显示了,原Activity才会调用onStop方法进入不可见状态。
当从Activity2回退到Activity1的时候,流程也是相似的,只是Activity1会在其余生命周期以前执行一次onRestart,跟前面的流程是相似的。读者能够看一下下面的日志打印,这里就再也不赘述了。
下面看一下切换到另外一个activity的生命周期日志打印:
这里咱们看到最后回调了onSaveInstanceState方法,前面咱们讲到了,当activity进入后台的时候,会调用该方法来保存数据。由于并不知道在后台时activity是否会被系统杀死。下面再看一下从activity2返回的时候,生命周期的日志打印:
running -> onPause -> onStop -> onSaveInstanceState -> onDestroy
onCreate -> onStart -> onRestoreInstanceState -> onResume
当因资源配置改变时,activity会销毁重建,最多见的就是屏幕旋转。这个时候属于异常状况的Activity生命结束。于是,在销毁的时候,会调用onSaveInstanceState来保存数据,在从新建立新的activity的时候,会调用onRestoreInstanceState来恢复数据。
看一下日志打印:
onDestroy
onCreate -> onStart -> onRestoreInstanceState -> onResume
这个流程跟上面的资源配置更改是很像的,只是每一个activity不可见的时候,会回调onSaveInstanceState提早保存数据,那么在被后台杀死的时候,就不须要再次保存数据了。
onActivityResult -> onRestart -> onResume
这里主要针对使用startActivityForResult方法启动另外一个activity,当该activity销毁并返回时,原activity的onActivityResult方法的执行时机。大部分流程和activity切换是同样的。但在返回原Activity时,onActivityResult方法会在其余全部的生命周期方法执行前被执行。看一下日志打印:
onPause -> onNewIntent -> onResume
这个流程是比较容易在学习生命周期的时候被忽略的。前面已经有讲到了关于onNewIntent的相关介绍,这里就再也不赘述。主要是记得若是当前activity正处于栈顶,那么会先回调onPause以后再回调onNewIntent。关于启动模式以及返回栈的设计这里就不展开讲了,记住生命周期就能够了。看一下日志打印:
到这里关于生命周期的一些应用知识就已经讲得差很少了,这一部分是深刻源码,去探究生命周期在源码中是如何实现的。这样对生命周期会有更加深入的理解,同时能够更加了解android系统的源码设计。
因为生命周期方法不少,笔者不可能一一讲解,这样篇幅就太大了且没有意义。这一部分的内容一共分为两个部分:第一部分是概述一下ActivityThread中关于每一个生命周期的调用方法,这样你们就懂得如何去寻找对应的源码来研究;第二部分是拿onResume这个方法来举例讲解,同时解释为何在第一次启动时,当onResume被调用时界面依然不可见。
咱们都知道,Activity的启动是受AMS调配的,那具体的调配方式是如何的呢?
经过Handler机制一文咱们知道,android的程序执行是使用handler机制来实现消息驱动型的。AMS想要控制Activity的生命周期,就必须不断地向主线程发送message;而程序想要执行AMS的命令,就必须handle这些message执行逻辑,两端配合,才能达到这种效率。
打个比方,领导要吩咐下属去工做,他确定不会把工做的具体流程都给下属,而只是会发个命令,如:给明天的演讲作个ppt,给我预定个下星期的飞机等等。那么下属,就必须根据这些命令来执行指定的逻辑。因此,在android程序,确定有一系列的逻辑,来分别执行来自AMS的“命令”。这就是ActivityThread中的一系列handlexxx方法。给个我在vs code中的搜索图感觉一下:
固然,应用程序不止收到AMS的管理,一样的还有WMS、PMS等等系统服务。系统服务是运行在系统服务进程的,当系统服务须要控制应用程序的时候,会经过Binder跨进程通讯把消息发送给应用程序。应用程序的Binder线程会经过handler把消息发送给主线程去执行。于是,从这里也能够看出,当应用程序刚被建立的时候,必须初始化的有主线程、binder线程、主线程handler、以及提早编写了命令的执行逻辑的类ActivityThread。光说不画假解释,画个图感觉一下:
回到咱们的生命周期主题。关于生命周期命令的执行方法主要有:
handleLaunchActivity; handleStartActivity; handleResumeActivity; handlePauseActivity; handleStopActivity; handleDestroyActivity;
具体的方法固然不止这么多,只是列出一些比较经常使用的。这些方法都在ActivityThread中。ActivityThread每一个应用程序有且只有一个,他是系统服务“命令”的执行者。
了解了AMS如何调配以后,那么他们的执行顺序如何肯定呢?AMS是先发送handleStartActivity命令呢,仍是先发送handleResumeActivity?这里就须要咱们对Activity的启动流程有必定的认知,感兴趣读者能够点击Activity启动流程前往学习,这里就不展开了。
最后再延伸一下,那,ActivityThread可不能够本身决定执行逻辑,而不理会AMS的命令呢?答案确定是no。你想啊,若是在公司里,你没有老板的赞成 ,你能动用公司的资源吗?回到Android系统也是同样的,没有AMS的受权,应用程序是没法获得系统资源的,因此AMS就保证了每个程序都必须符合必定的规范。关于这方面的设计,读者感兴趣能够阅读context机制这篇文章了解一下,从新认识一下context。
好了,扯得有点远,咱们回到主题。下面呢就不展开去跟踪整个流程了,而是定位到具体的handle方法去看看具体执行了什么逻辑,对源码流程感性去的读者能够自行研究,限于篇幅这里就不展开了。下面主要介绍handleResumeActivity
方法。
根据咱们前面的学习,handleResumeActivity
确定是在handleLaunchActivity
和handleStartActivity
以后被执行的。咱们直接来看源码:
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, String reason) { ... final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason); ...; if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) { ... if (r.activity.mVisibleFromClient) { r.activity.makeVisible(); } } ... }
代码我截取了两个很是重要的部分。performResumeActivity
最终会执行onResume
方法;activity.makeVisible();
是真正让界面显示在屏幕个上的方法,咱们看一下makeVisible()
:
void makeVisible() { if (!mWindowAdded) { ViewManager wm = getWindowManager(); wm.addView(mDecor, getWindow().getAttributes()); mWindowAdded = true; } mDecor.setVisibility(View.VISIBLE); }
若是还没有添加到屏幕上,那么会调用windowManager的addView方法来添加,以后,activity界面才真正显示在屏幕上。回应以前的问题:为何在onResume弹出popupWindow会抛异常而弹出dialog却不会?缘由就是这个时候activity的界面还没有添加到屏幕上,而popupWindow须要依附于父界面,这个时候弹出就会抛出token is null
异常了。而Dialog属于应用层级窗口,不须要依附于任何窗口,因此dialog在onCreate方法中弹出都是没有问题的。为了验证咱们的判断,我在生命周期中打印decorView的windowToken,当decorView被添加到屏幕上后,就会被赋值token了,看日志打印:
能够看到,直到onPostResume方法执行,界面依旧没有显示在屏幕上。而直到onWindowFocusChange被执行时,界面才是真正显示在屏幕上了。
好了,让咱们再回到一开始的源码,深刻performResumeActivity方法中看看,在哪里执行了onResume方法:
public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest, String reason) { ... try { ... if (r.pendingIntents != null) { // 判断是否须要执行newIntent方法 deliverNewIntents(r, r.pendingIntents); r.pendingIntents = null; } if (r.pendingResults != null) { // 判断是否须要执行onActivityResult方法 deliverResults(r, r.pendingResults, reason); r.pendingResults = null; } // 回调onResume方法 r.activity.performResume(r.startsNotResumed, reason); r.state = null; r.persistentState = null; // 设置状态 r.setState(ON_RESUME); reportTopResumedActivityChanged(r, r.isTopResumedActivity, "topWhenResuming"); } ... }
这个方法的重点就是,先判断是不是须要执行onNewIntent或者onActivityResult的场景,若是没有则执行调用performResume
方法,咱们深刻performResume
看一下:
final void performResume(boolean followedByPause, String reason) { dispatchActivityPreResumed(); performRestart(true /* start */, reason); ... mInstrumentation.callActivityOnResume(this); ... onPostResume(); ... } public void callActivityOnResume(Activity activity) { activity.mResumed = true; activity.onResume(); ... }
一样只看重点。首先会调用performRestart方法,这个方法内部会判断是否须要执行onRestart方法和onStart方法,若是是从别的activity返回这里是确定要执行的。而后使用Instrumentation来回调Activity的onResume方法。当onResume回调完成后,会再调用onPostResume()方法。
那么到这里关于handleResumeActivity的方法就讲完了,为何在onResume甚至onPostResume方法被回调的时候界面还没有显示,也有了更加深入的认识。具体的代码逻辑很是多,而关于生命周期的代码我只挑了重点来说,其余的源码,感兴趣的读者能够自行去查阅源码。笔者这里更多的是充当一个抛砖引玉的效果。要从源码中学习到知识,就必须本身手动去阅读源码,跟着文章看完事实上收获是不大的。
在笔者认为,每个知识,都是在具体的场景下为了解决具体的问题,经过权衡各类条件设计出来的。在学习了每个知识以后,笔者老是喜欢反过来,思考一下这一块知识的底层设计思想是什么,他是须要解决什么问题,权衡了什么条件。经过不断思考来从一个更高的角度来看待每个知识点。
要理解生命周期的设计,首先须要理解Activity自己。想一下,若是没有Activity,那么咱们该如何编写程序?有没有突然反应到,没有了activity,咱们的程序竟无处下手?由于这涉及到Activity的一个最大的做用:Activity
类是 Android 应用的关键组件,而 Activity 的启动和组合方式则是该平台应用模型的基本组成部分。
相信不少读者都写过c语言、java或者其余语言的课程设计,咱们的程序入口就是main
函数。从main函数开始,根据用户的输入来进入不一样的功能模块,如更改信息模块、查阅模块等等。以功能模块为基本组成部分的应用模型是咱们最初的程序设计模型。而android程序,咱们会说这个程序有几个界面。咱们更关注的是界面之间的跳转,而不是功能模块之间的跳转。咱们在设计程序的时候,咱们会说这个界面有什么功能,那个界面有什么功能,多个界面之间如何协调。对于用户来讲,他们感知的也是一个个独立的界面。当咱们经过通信软件调用邮箱app的发送邮件界面时,咱们喜欢看到的只是发送邮件的界面,而不须要看到收件箱、登陆注册等界面。以功能模块为应用模型的设计从一个主功能模块入口,而后经过用户的输入去调用不一样的功能模块。与其相似,android程序也有一个主界面,经过这个主界面,接受用户的操做去调用其余的界面。组成android程序的,是一个个的界面,而每个界面,对应一个Activity。所以,Activity是android平台应用模型的基本组成成分。
功能模块的应用模型从main方法进入主功能模块,而android程序从ActivityThread的main方法开始,接收AMS的调度启动“LaunchActivity”,也就是咱们在AndroidManifest中配置为main的activity,当应用启动的时候,就会首先打开这个activity。那么第一个界面被打开,其余的界面就根据用户的操做来依次跳转了。
那如何作到每一个界面之间彼此解耦、各自的显示不发生混乱、界面之间的跳转有条不紊等等?这些工做,官方都帮咱们作好了。Activity就是在这个设计思想下开发出来的。当咱们在Activity上开发的时候,就已经沿用了他的这种设计思想。当咱们开发一个app的时候,最开始要考虑的,是界面如何设计。设计好界面以后,就是考虑如何开发每一个界面了。那咱们如何自定义好每个界面?如何根据咱们的需求去设计每一个界面的功能?Activity并无main方法,咱们的代码该写在哪里被执行?答案就是:生命周期回调方法。
到这里,你应该能够理解为何启动activity并非一句new就能够解决的吧?Activity承担的责任很是多,须要初始化的逻辑也很是多。当Activity被启动,他会根据自身的启动状况,来回调不一样的生命周期方法。其中,承担初始化整个界面已经各个功能组件的初始化任务的就是onCreate方法。他有点相似于咱们功能模块的入口函数,在这里咱们经过setContentView来设计咱们界面的布局,经过setOnClickListenner来给每一个view设置监听等等。在MVVM设计模式中,还须要初始化viewModel、绑定数据等等。这是生命周期的第一个很是重要的意义所在。
而当界面的显示、退出,咱们须要为之申请或者释放资源。如我上文举的相机例子,我在微信的扫一扫申请了相机权限,若是进入后台的时候没有释放资源,那么打开系统相机就没法使用了,资源被占领了。所以,生命周期的另外一个重要的做用就是:作好资源的申请与释放,避免内存泄露。
其余生命周期的做用,如界面数据恢复、界面切换逻辑处理等等就再也不赘述了,前面已经都有涉及到。
这一部分的重点就是理解android应用程序是以Activity为基本组成部分的应用模型这个点。当界面的启动以及不一样界面之间进行切换的时候,也就能够更加感知生命周期的做用了。
关于Activity生命周期的内容,在一篇文章讲完整是不可能的。当对他研究地越深,涉及到内容就会越多。每一个知识点就是像是瓜藤架上的一个瓜,若是单纯摘瓜,那就是一个瓜;若是抓着藤蔓往外拔,那么整个架子都会被扯出来。这篇文章也当是抛砖引玉,在讲生命周期相关的知识讲完以后,提供给读者一个思考的思路。
但愿文章对你有帮助。
全文到此,原创不易,以为有帮助能够点赞收藏评论转发。
笔者才疏学浅,有任何想法欢迎评论区交流指正。
如需转载请评论区或私信交流。另外欢迎光临笔者的我的博客:传送门