写点什么

【Android 高级架构师系统学习文章】Android 基础 -Activity 全方位解析

用户头像
Android架构
关注
发布于: 刚刚

②用户打开新的 Activiy 的时候,上述 Activity 的回调如下:onPause()->onStop()


③再次回到原 Activity 时,回调如下:onRestart()->onStart()->onResume()


④按 back 键回退时,回调如下:onPause()->onStop()->onDestory()


⑤按 Home 键切换到桌面后又回到该 Actitivy,回调如下:onPause()->onStop()->onRestart()->onStart()->onResume()


⑥调用 finish()方法后,回调如下:onDestory()(以在 onCreate()方法中调用为例,不同方法中回调不同,通常都是在 onCreate()方法中调用)

2.特殊情况下的生命周期

上面是普通情况下 Activity 生命周期的一些流程,但是在一些特殊情况下,Activity 的生命周期的经历有些异常,下面就是两种特殊情况。①横竖屏切换在横竖屏切换的过程中,会发生 Activity 被销毁并重建的过程。


在了解这种情况下的生命周期时,首先应该了解这两个回调:onSaveInstanceState 和 onRestoreInstanceState


在 Activity 由于异常情况下终止时,系统会调用 onSaveInstanceState 来保存当前 Activity 的状态。这个方法的调用是在 onStop 之前,它和 onPause 没有既定的时序关系,该方法只在 Activity 被异常终止的情况下调用。当异常终止的 Activity 被重建以后,系统会调用 onRestoreInstanceState,并且把 Activity 销毁时 onSaveInstanceState 方法所保存的 Bundle 对象参数同时传递给 onRestoreInstanceState 和 onCreate 方法。因此,可以通过 onRestoreInstanceState 方法来恢复 Activity 的状态,该方法的调用时机是在 onStart 之后。其中 onCreate 和 onRestoreInstanceState 方法来恢复 Activity 的状态的区别:?onRestoreInstanceState 回调则表明其中 Bundle 对象非空,不用加非空判断。onCreate 需要非空判断。建议使用 onRestoreInstanceState。



横竖屏切换的生命周期:onPause()->onSaveInstanceState()-> onStop()->onDestroy()->onCreate()->onStart()->onRestoreInstanceState->onResume()


可以通过在 AndroidManifest 文件的 Activity 中指定如下属性:


android:configChanges = "orientation| screenSize"


来避免横竖屏切换时,Activity 的销毁和重建,而是回调了下面的方法:


@Overridepublic void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);}


②资源内存不足导致优先级低的 Activity 被杀死 Activity 优先级的划分和下面的 Activity 的三种运行状态是对应的。


(1) 前台 Activity——正在和用户交互的 Activity,优先级最高。


(2) 可见但非前台 Activity——比如 Activity 中弹出了一个对话框,导致 Activity 可见但是位于后台无法和用户交互。


(3) 后台 Activity——已经被暂停的 Activity,比如执行了 onStop,优先级最低。


当系统内存不足时,会按照上述优先级从低到高去杀死目标 Activity 所在的进程。我们在平常使用手机时,能经常感受到这一现象。这种情况下数组存储和恢复过程和上述情况一致,生命周期情况也一样。

3.Activity 的三种运行状态

①Resumed(活动状态)


又叫 Running 状态,这个 Activity 正在屏幕上显示,并且有用户焦点。这个很好理解,就是用户正在操作的那个界面。


②Paused(暂停状态)


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


③Stopped(停止状态)


当 Activity 完全不可见时,此时 Activity 还在后台运行,仍然在内存中保留 Activity 的状态,并不是完全销毁。这个也很好理解,当跳转的另外一个界面,之前的界面还在后台,按回退按钮还会恢复原来的状态,大部分软件在打开的时候,直接按 Home 键,并不会关闭它,此时的 Activity 就是 Stopped 状态。

二、Activity 的启动模式

1.启动模式的类别

Android 提供了四种 Activity 启动方式:


标准模式(standard)栈顶复用模式(singleTop)栈内复用模式(singleTask)单例模式(singleInstance)

2.启动模式的结构——栈

Activity 的管理是采用任务栈的形式,任务栈采用“后进先出”的栈结构。


3.Activity 的 Launc

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


hMode

(1)标准模式(standard)

每启动一次 Activity,就会创建一个新的 Activity 实例并置于栈顶。谁启动了这个 Activity,那么这个 Activity 就运行在启动它的那个 Activity 所在的栈中。


例如:Activity A 启动了 Activity B,则就会在 A 所在的栈顶压入一个新的 Activity。



特殊情况,如果在 Service 或 Application 中启动一个 Activity,其并没有所谓的任务栈,可以使用标记位 Flag 来解决。解决办法:为待启动的 Activity 指定 FLAG_ACTIVITY_NEW_TASK 标记位,创建一个新栈。


应用场景:?绝大多数 Activity。如果以这种方式启动的 Activity 被跨进程调用,在 5.0 之前新启动的 Activity 实例会放入发送 Intent 的 Task 的栈的顶部,尽管它们属于不同的程序,这似乎有点费解看起来也不是那么合理,所以在 5.0 之后,上述情景会创建一个新的 Task,新启动的 Activity 就会放入刚创建的 Task 中,这样就合理的多了。

(2)栈顶复用模式(singleTop)

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


@Overrideprotected void onNewIntent(Intent intent) {super.onNewIntent(intent);}


由于不会重建一个 Activity 实例,则不会回调其他生命周期方法。如果栈顶不是新建的 Activity,就会创建该 Activity 新的实例,并放入栈顶。



应用场景:?在通知栏点击收到的通知,然后需要启动一个 Activity,这个 Activity 就可以用 singleTop,否则每次点击都会新建一个 Activity。当然实际的开发过程中,测试妹纸没准给你提过这样的 bug:某个场景下连续快速点击,启动了两个 Activity。如果这个时候待启动的 Activity 使用 singleTop 模式也是可以避免这个 Bug 的。同 standard 模式,如果是外部程序启动 singleTop 的 Activity,在 Android 5.0 之前新创建的 Activity 会位于调用者的 Task 中,5.0 及以后会放入新的 Task 中。

(3)栈内复用模式(singleTask)

该模式是一种单例模式,即一个栈内只有一个该 Activity 实例。该模式,可以通过在 AndroidManifest 文件的 Activity 中指定该 Activity 需要加载到那个栈中,即 singleTask 的 Activity 可以指定想要加载的目标栈。singleTask 和 taskAffinity 配合使用,指定开启的 Activity 加入到哪个栈中。


<activity android:name=".Activity1"android:launchMode="singleTask"android:taskAffinity="com.lvr.task"android:label="@string/app_name"></activity>


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

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
【Android高级架构师系统学习文章】Android基础-Activity全方位解析