Andorid: Activity 全解析

1.生命周期:

 

Andorid: Activity 全解析_第1张图片

1.1 基础生命周期

老图了,就不解释详细了,重点提下:

1.1.1 Activity3种运行状态:Resumed、Paused、Stopped

Paused:这个Activity在屏幕上是可见的,但是并不是在屏幕最前端的那个Activity。比如有另一个非全屏或者透明的Activity是Resumed状态,没有完全遮盖这个Activity。

Stopped:当Activity完全不可见时,此时Activity还在后台运行,仍然在内存中保留Activity的状态,并不是完全销毁。

1.1.2 各生命周期

onStart():表示Activity正在被启动,即将开始,没有出现在前台,这时Activity已经出现了。注意:onStart时,对应Paused状态,Activity可见,不可点击(交互),不可获取焦点。

onResume():表示Activity已经可见了,并且出现在前台并开始活动。注意:onResume时,对应Resumed状态,Activity可见,可点击(交互),可获取焦点。

onPause():表示Activity暂停,仍可见,正常情况下,紧接着onStop就会被 调用。在特殊情况下,如果这个时候快速地回到当前Activity,那么onResume就会 被调用(极端情况)。onPause中不能进行耗时操作,会影响到新Activity的显 示。因为onPause必须执行完,新的Activity的onResume才会执行。 注意:onPause时,对应Paused状态,Activity可见,不可点击(交互),不可获取焦点。

onStop():表示Activity即将停止,不可见,位于后台。可以做稍微重量级的回收 工作,同样不能太耗时。注意:onStop时,对应Stopped状态,Activity不可见,不可点击(交互),不可获取焦点。

onDestory():表示Activity即将销毁,可以做一些回收工作和最终的资源回收。

 

1.2 特殊生命周期

onSaveInstanceState():当Activity遇到意外情况退出时调用保存数据,以下5种情况被调用:

(1)、当用户按下HOME键时。
(2)、从最近应用中选择运行其他的程序时(长按手机home键或者按下菜单键时)。
(3)、按下电源按键(关闭屏幕显示)时。
(4)、从当前Activity启动一个新的Activity时。
(5)、屏幕方向切换时(无论竖屏切横屏还是横屏切竖屏都会调用)。

注意:onSaveInstanceState和onPause没有固定时序,但两者都确定是在onStop之前调用,后文为了方便,将onSaveInstanceState放到onPause后面。

onRestoreInstanceState():只有在Activity确实是被系统回收,重新创建Activity的情况下才会被调用,用于重建时恢复数据。

注意:严格意义来说,onSaveInstanceState、onRestoreInstanceState并不算Activity的生命周期,因为它们不是一定被调用的。onRestoreInstanceState只有在Activity确实是被系统回收,重新创建Activity的情况下(即重走onCreate)才会被调用,比如旋屏,Activity确实被销毁后又重新onCreate。而HOME键切换则不会。

 

1.3 通常状况下生命周期调用情况

(1)针对一个特定的Activity,第一次启动,回调如下:onCreate()->onStart()>onResume()

(2)用户打开新的Activiy的时候,原Activity的回调如下:onPause()->onSaveInstanceState()->onStop()

(3)再次回到原Activity时,回调如下:onRestart()->onStart()->onResume()    注意:虽然调用了onSaveInstanceState,但onRestoreInstanceState并不会被调用。

(4)按back键回退时,回调如下:onPause()->onStop()->onDestory()    注意:因为back为主动退出行为,所以不会调用onSaveInstanceState。

(5)按Home键切换到桌面后又回到该Actitivy,回调如下:onPause()->onSaveInstanceState()->onStop()>onRestart()->onStart()->onResume()     注意:虽然调用了onSaveInstanceState,但onRestoreInstanceState并不会被调用。

(6)调用finish()方法后,回调如下:onPause()->onStop()->onDestory() 

(7)横竖屏切换,回调如下:onPause() -> onSaveInstanceState() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onRestoreInstanceState() -> onResume()    注意:可以指定 android:configChanges = "orientation| screenSize" 来避免横竖屏切换时,Activity被销毁和重建,指定后,Activity不会调用onDestroy和onCreate,而是回调了下面的方法:

          @Override
          public void onConfigurationChanged(Configuration newConfig) 

 

2 启动模式

2.1 标准模式 standard

每启动一次Activity,就会创建一个新的Activity实例并置于栈顶。谁启动了这个 Activity,那么这个Activity就运行在启动它的那个Activity所在的栈中
注意:如果在Service或Application中启动一个Activity,其并没有所谓的任务栈,可以使用标记位Flag来解决,即为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位,创建一个新栈。

2.2 栈顶复用模式 singleTop

如果需要新建的Activity位于任务栈栈顶,那么此 Activity 的实例就不会重建,而是重用栈顶的实例。

注意:因为不是重建,所以不会重新调用onCreate()  ,而是走onNewIntent() ,但是由于确实有启动且换界面的效果,所以生命周期为 onPause()  -> onNewIntent()  -> onResume()

同 standard模式,如果是外部程序启动singleTop的Activity,在Android 5.0之前新创建的Activity会位于调用者的Task中,5.0及以后会放入新的Task中
 

2.3 栈内复用模式 singleTask

一个栈内只有一个该Activity实例,如果该Activity被重复启动,则判断栈顶的Activity是否是需要启动的Activity,不是则出栈,直到栈顶Activity是被启动的那个Activity。singleTask的Activity生命周期为:onNewIntent() -> onRestart() -> onStart() -> onResume()

注意:可以通过在 AndroidManifest文件中指定singleTask模式的Activity需要加载到那个栈中,使用taskAffinity属性。如果指定的栈不存在,则创建。

关于taskAffinity的值:每个Activity都有taskAffinity属性,这个属性指出了它希望 进入的Task。如果一个Activity没有显式的指明该Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果Application也没有指明,那么该taskAffinity的值就等于包名。

值得一提:如果App的启动Activity被设置为singleTask,则Home键退出到桌面,然后再点击App图标进入,则会“重启”app。这里并非真正的重启,启动页Activity不会重建(不会走onCreate,走onNewIntent() -> onRestart() -> onStart() -> onResume()),应用的Application更不会重建,而是栈中启动页Activity前的其它所有Activity都被出栈了。

原因可能和Task调度相关,在Launcher启动app,会先拉起启动页Activity,然后将已有的Task调度到前台,猜测,待验证。

解决:去掉启动页的singleTask或singleInstance模式。部分机型不在这两种模式下都可能出现这个问题,如果存在,则在启动页Activity的onCreate里加上:
if (!this.isTaskRoot()) { // 判断当前activity是不是所在任务栈的根
    Intent intent = getIntent();
    if (intent != null) {
        String action = intent.getAction();
        if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && Intent.ACTION_MAIN.equals(action)) {
            finish();
            return;
        }
    }

Task(任务)是Android Framework中的一个概念,Task是由一系列相关的Activity组成的,是一组相关Activity的集合,以栈的形式来管理的。在启动模式为standard或singleTop时,一般是在同一个任务中对Activity进行调度,而在启动模式为singleTask或singleInstance时,一般会对Task任务进行整体调度,包括:

(1)按Home键,将之前的Task切换到后台
(2)长按Home键,会显示出最近执行过的Task列表
(3)在Launcher或HomeScreen点击app图标,开启一个新Task,或者是将已有的Task调度到前台

2.4 单例模式 singleInstance

打开该Activity时,直接创建一个新的任 务栈,并创建该Activity实例放入新栈中。一旦该模式的Activity实例已经存在于某个 栈中,任何应用再激活该Activity时都会重用该栈中的实例系统打电话界面的Activity就是singleInstance

2.5 Activity的Flags 

Activity的Flags很多,用于设定Activity的启动模式,可以在启动Activity时,通过Intent的addFlags()方法设置。 (1)FLAG_ACTIVITY_NEW_TASK    其效果与指定Activity为singleTask模式一致。

(2)FLAG_ACTIVITY_SINGLE_TOP    其效果与指定Activity为singleTop模式一致。

(3)FLAG_ACTIVITY_CLEAR_TOP    具有此标记位的Activity,当它启动时,在同一 个任务栈中所有位于它上面的Activity都要出栈。如果和singleTask模式一起出现, 若被启动的Activity已经存在栈中,则清除其之上的Activity,并调用该Activity的 onNewIntent方法。如果被启动的Activity采用standard模式,那么该Activity连同之 上的所有Activity出栈,然后创建新的Activity实例并压入栈中。
其它具体参考:https://www.jianshu.com/p/537aa221eec4/

你可能感兴趣的:(Android)