activity 启动模式_1-1-Android基础知识-Activity

为什么会有Activity?

安卓应用开发的时候,首先接触到的就是四大组件之一 Activity,可曾深入思考一下,为什么会有 Activity,安卓系统设计这个组件的目的是什么呢?

  1. Activity 是系统与用户交互的载体,由于用户的行为不可预期性,导致 Activity 的状态比较复杂,管理起来也比较麻烦,衍生出一套解决方案
  2. 安卓系统中的很多应用,没有可见的界面,可以没有 Activity。Activity 很重要,但并非不可缺少。

Activity 的生命周期

关键方法

  • onCreate
  • onStart
  • onResume
  • onPause
  • onStop
  • onDestory
85de64d96f184cd8a02b7956719f5180

生命周期回调中的方法,不可以做耗时的操作,尤其是onResume和onPause,这两个方法在 Activity 的状态管理中,会频繁的调用。

典型场景下的生命周期回调

A ---> B ---> A

标准模式下,A 启动 B, B 再返回 A 页面

D/LifeCycle: A1 oncreateD/LifeCycle: A1 onStartD/LifeCycle: A1 onResumeD/LifeCycle: A1 onPauseD/LifeCycle: A2 OnCreateD/LifeCycle: A2 onStartD/LifeCycle: A2 onResumeD/LifeCycle: A1 onStopD/LifeCycle: A2 onPauseD/LifeCycle: A1 onStartD/LifeCycle: A1 onResumeD/LifeCycle: A2 onDestroy

A 页面启动后,旋转屏幕

默认配置下,旋转屏幕

D/LifeCycle: A1 oncreateD/LifeCycle: A1 onStartD/LifeCycle: A1 onResumeD/LifeCycle: A1 onPauseD/LifeCycle: A1 onStopD/LifeCycle: A1 onDestroyD/LifeCycle: A1 oncreateD/LifeCycle: A1 onStartD/LifeCycle: A1 onRestoreInstanceStateD/LifeCycle: A1 onResume

A 页面中还有一些关键方法,同时也添加了日志,但是并没有输出

  • onConfigChange
  • onSaveInstanceState

但这两个方法并没有被调用

    @Override    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {        super.onRestoreInstanceState(savedInstanceState);        Log.d("LifeCycle","A1 onRestoreInstanceState");    }    @Override    public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {        super.onSaveInstanceState(outState, outPersistentState);        Log.d("LifeCycle","A1 onSaveInstanceState");    }    @Override    public void onConfigurationChanged(@NonNull Configuration newConfig) {        super.onConfigurationChanged(newConfig);        Log.d("LifeCycle","A1 onConfigureChange");    }    

关于生命周期的两个扩展问题

  1. 什么情况下,A 页面会调用 onPause ,但不会调用 onStop 方法
  2. onCreate 方法中的 Bundle 和 onRestoreInstanceState 中 Bundle 一样吗?能重复获取吗?

Activity 启动模式和任务栈管理

  • standard
  • singleTask
  • singleTop
  • singleInstance

如果对这个不了解,可以先阅读官方文档 Tasks and back stack,官方的讲解非常的清晰易懂,同时配有插图辅助理解。

以下内容摘自官方文档,配合简要说明。

standard

Default. The system creates a new instance of the activity in the task from which it was started and routes the intent to it. The activity can be instantiated multiple times, each instance can belong to different tasks, and one task can have multiple instances.

关键点:默认会初始化多次,每个任务栈可以有多个实例

74dec1a0d60548469efd7b648896c905
b20ea53b501e4fabacb213b09d7da756

singleTop

If an instance of the activity already exists at the top of the current task, the system routes the intent to that instance through a call to its onNewIntent() method, rather than creating a new instance of the activity. The activity can be instantiated multiple times, each instance can belong to different tasks, and one task can have multiple instances (but only if the activity at the top of the back stack is not an existing instance of the activity).
For example, suppose a task's back stack consists of root activity A with activities B, C, and D on top (the stack is A-B-C-D; D is on top). An intent arrives for an activity of type D. If D has the default "standard" launch mode, a new instance of the class is launched and the stack becomes A-B-C-D-D. However, if D's launch mode is "singleTop", the existing instance of D receives the intent through onNewIntent(), because it's at the top of the stack—the stack remains A-B-C-D. However, if an intent arrives for an activity of type B, then a new instance of B is added to the stack, even if its launch mode is "singleTop".

关键点:栈顶的如果是即将要启动的 Activity,会直接启动当前 Activity,同时调用 onNewIntent() 方法,而不是 onCreate 方法

singleTask

The system creates a new task and instantiates the activity at the root of the new task. However, if an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its onNewIntent() method, rather than creating a new instance. Only one instance of the activity can exist at a time.

关键点:首次创建该 Activity时,新建一个 task;非首次,共用之前的,同时回调 onNewIntent()方法

同时 singleTask 下,Activity 的生命周期回调也会有所不同

A--->B--->A 日志如下

D/LifeCycle: A1 oncreateD/LifeCycle: A1 onStartD/LifeCycle: A1 onResumeD/LifeCycle: A1 onPauseD/LifeCycle: A2 OnCreateD/LifeCycle: A2 onStartD/LifeCycle: A2 onResumeD/LifeCycle: A1 onStopD/LifeCycle: A2 onPauseD/LifeCycle: A1 onStartD/LifeCycle: A1 onNewIntentD/LifeCycle: A1 onResumeD/LifeCycle: A2 onDestroy 

再次启动 A 的时候,B 直接回调了 onDestory 方法,返回栈被清空。

singleInstance

Same as "singleTask", except that the system doesn't launch any other activities into the task holding the instance. The activity is always the single and only member of its task; any activities started by this one open in a separate task.

关键点:独占任务栈

A-->B-->A -->返回-->返回
生命周期的日志如下

D/LifeCycle: A1 oncreateD/LifeCycle: A1 onStartD/LifeCycle: A1 onResumeD/LifeCycle: A1 onPauseD/LifeCycle: A2 OnCreateD/LifeCycle: A2 onStartD/LifeCycle: A2 onResumeD/LifeCycle: A1 onStopD/LifeCycle: A2 onPauseD/LifeCycle: A1 onStartD/LifeCycle: A1 onNewIntentD/LifeCycle: A1 onResumeD/LifeCycle: A1 onPauseD/LifeCycle: A2 onStartD/LifeCycle: A2 onResumeD/LifeCycle: A1 onStopD/LifeCycle: A1 onDestroyD/LifeCycle: A2 onPauseD/LifeCycle: A2 onDestroy

B 再次启动 A 后,之前的任务栈被共用,A 在一个新的任务栈中。

Intent FLAG

  • FLAG_ACTIVITY_NEW_TASK
  • FLAG_ACTIVITY_SINGLE_TOP
  • FLAG_ACTIVITY_CLEAR_TOP

如果同时在 manifest 和 Intent FLAG 定义,最终会以 Intent FLAG 中定义的为准。

FLAG_ACTIVITY_NEW_TASK

This produces the same behavior as the "singleTask" launchMode value

关键点:和 singleTask 效果一样。

FLAG_ACTIVITY_SINGLE_TOP

This produces the same behavior as the "singleTop" launchMode value

关键点:和 singleTop 效果一样。

FLAG_ACTIVITY_CLEAR_TOP

If the activity being started is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it are destroyed and this intent is delivered to the resumed instance of the activity (now on top), through onNewIntent()).

FLAG_ACTIVITY_CLEAR_TOP is most often used in conjunction with FLAG_ACTIVITY_NEW_TASK. When used together, these flags are a way of locating an existing activity in another task and putting it in a position where it can respond to the intent.

关键点:如果已经在当前任务栈,会清空上面的页面,把自己提升到栈顶,同时回调 onNewIntent(),一般和FLAG_ACTIVITY_NEW_TASK共用,与singleTask 有点类似。

TaskAffinity

taskAffinity 是为了更好的管理 Activity 和任务栈的关系 。默认情况下,同一个 App 的所有的 Activity 都在一个 task 中(标准模式)。但如果有多个 task,当启动一个 Activity 时,优先选择哪一个 task 呢?可以通过 taskAffinity 来定制。并且不同的 App,也可以共享同一个 Affinity。一个 App 中,也可以有多个不同的 taskAffinity。

再复杂一些的任务栈管理方案,在项目中也很少会用到了。

Activity 的数据恢复和状态恢复

什么情况下需要数据和状态恢复呢?

  1. 异常退出,因内存等原因,被系统回收,再次回到前台时,能够恢复离开时的状态
  2. 异常中断,比如看新闻时,被一个电话打断,接完电话再回来时,希望继续刚才阅读的位置继续。

和状态恢复相关的关键方法有两个

    @Override    public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {        super.onSaveInstanceState(outState, outPersistentState);        Log.d("LifeCycle","A2 onSaveInstanceState");    }    @Override    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {        super.onRestoreInstanceState(savedInstanceState);        Log.d("LifeCycle","A2 onRestoreInstanceState");    }    

实际验证下来,这两个方法的调用都不正常,在不同版本、不同手机上会有差异,可靠性无法保障。

横竖屏切换时,Activity 生命周期的变化

在这里,典型场景下 Activity 生命周期变化 中,已经说明了默认情况下(不设置 Activity 的 android:configChanges 属性),旋转屏幕Activity 生命周期的变化。还有另外一个场景,做一些系统配置后,生命周期的回调会发生改变。

再看一下 设置 android:configChanges= "orientation" 属性后,生命周期的变化

A 启动-->旋转-->旋转-->退出

D/LifeCycle: A1 oncreateD/LifeCycle: A1 onStartD/LifeCycle: A1 onResumeD/LifeCycle: A1 onPauseD/LifeCycle: A1 onStopD/LifeCycle: A1 onDestroyD/LifeCycle: A1 oncreateD/LifeCycle: A1 onStartD/LifeCycle: A1 onRestoreInstanceStateD/LifeCycle: A1 onResumeD/LifeCycle: A1 onPauseD/LifeCycle: A1 onStopD/LifeCycle: A1 onDestroyD/LifeCycle: A1 oncreateD/LifeCycle: A1 onStartD/LifeCycle: A1 onRestoreInstanceStateD/LifeCycle: A1 onResumeD/LifeCycle: A1 onPauseD/LifeCycle: A1 onStopD/LifeCycle: A1 onDestroy

属性配置为 android:configChanges= "orientation|screenSize" 后,生命周期的变化

A 启动-->旋转-->旋转-->退出

D/LifeCycle: A2 OnCreateD/LifeCycle: A2 onStartD/LifeCycle: A2 onResumeD/LifeCycle: A2 onConfigureChangeD/LifeCycle: A2 onConfigureChangeD/LifeCycle: A2 onPauseD/LifeCycle: A2 onDestroy

所以,在使用的时候,需要把 screenSize 和 orientation 配合使用。

Activity 的扩展问题 - TODO

Activity 这个主题下,遗留的 7 个扩展问题,这些问题的解答,会在
Android 高级 完成后再来解决,每个扩展问题,都可以单独一个章节阐述,也是我们在项目开发中,知道深入思考的问题。

  • 影响 Activity 启动速度的因素有哪些?如何优化 Activity 的启动速度?
  • 微信、支付宝支付界面的启动方案如何设计,有哪些借鉴意义?
  • Activity 的数据恢复的其他方案有哪些(至少 3 种),这些方案各有哪些优劣?
  • LifeCycle 如何观察 Activity 的声明周期?使用了何种设计模式,阐述下核心的设计流程
  • 四种启动模式,各自典型的应用场景有哪些,如果自己设计管理 Activity 的任务栈,有哪些思路可以参考?
  • 从 Activity 关键生命周期方法中,如何统计一个 Activity 的用户使用时长,在做的时候,应该注意哪些问题?
  • Activity 、Window和 View 之间的关系
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值