Android Activity启动模式和栈管理

Acticity的标准生命周期

首先activity 的基本的生命周期
顺序排列
(1)onCreate() : 表示activity 正在被创建,在这个方法中我么可以做一些初始化操作

(2)onRestart () : 表示activity 正在重新被启动 , 第一次启动activity不会调用,当activity从不可见变为可见是调用,这种一般是用户行为导致,比如按home键或者打开一个新的activity就会让当前activity暂停调用onPasue和onStop,再重新回到这个activity就会调用onRestart

(3)onStart() : 表示activity正在被启动,即将开始 activity已经可见了,但是还没有出现在前台还无法和用户交互,这个时候可以理解为activity已经可见了,但是我们还看不到

(4)onResume() : 表示activity已经可见,并且出现在前台可以和用户交互,这里比较一下onStart和onResume 的区别,onStart的时候activity还在可见还在后台,onResume可见已经在前台

(5)onPause() : 表示activity正在停止,此时可以做一些,储存数据和停止动画操作,但是不能做太耗时的操作

(6) onStop() : 表示activity即停止,可以做一些稍微重量级的操作但依然不能太耗时

(7)onDestory(): activity即将被销毁 ,activity最后一个回调,我们可以在这里面做一些资源的回收和释放

这里写图片描述

(1) 用户第一次启动生命周期:onCreate()–onStart()–onResume()
(2) 用户打开新的Activity或者切换到屏幕:onPause–onStop,这里有个特殊情况,如果新开的Activity采用的透明主题,那么不会调用onStop
(3)用户再次返回原Activity:onRestart–onStart–onResume
(4)当用户按下back键:onPause–onStop–onDestory
(5)Activity被系统回收后,生命周期和(1)一样,只是生命周期一样,但过程不一样,下面会说明
(6)从声明周期来说,onCreate和onDestory是配对的,标志着Activity创建和销毁,并只可能调用一次,onStart和onStop是配对的,标志着是否可见,onResume和onPause是配对的,标志着是否在前台

现在有一个问题

问题1 根据描述 onStart onResume和 onPause onStop描述都差不多,具体有什么区别呢

onStart和onStop 是根据activity是否可见来判断的 onResume 和 onPause是根据activity是否在前台判断的

问题2 现有一个activityA 打开一个ActivityB 那么activityA 的onpause 和 activityB的 onResume那个先调用呢

根据源码是 activityA的onPause先调用

异常情况下的生命周期

当Activity在异常情况下终止,系统会调用onSaveInstanceState来保存当前Activity的状态,这个方法的调用时机,是在onStop之前,他和onPause没有时序关系,它既可在onPause之前调用,也可以在onPause之后调用,正常情况是不会调用这个方法的,当Activity被重新创建时,系统会调用onRestorInstanceState,并把Activity销毁时的Bundle传给onRestorInstanceState和onCreate,因此我们可以通过这个俩个方法判断Acticity是否重建,如果重建了就取出之前保存的数据并恢复,在onStart之后调用
这里写图片描述

我们都知道当旋转屏幕时会导致Activity 销毁重新创建 ,那么有没有可能不让他销毁呢,答案是有的配置activity的confingChanges 就可以避免android:configChanges=”orientation”
一些confingChanges 的基本配置
这里写图片描述

Activity的启动模式

(1) standard: 标准模式,每次启动Acticity都会创建一个新的Activity实例,并且将其压如任务栈栈顶,而不管这个Activity是否已经存在(activity的三个回调都会启用,onCreate—onStart–onResume) ,这是一种典型的多实例实现,一个任务栈可以有多个实例,一个实例可以属于不同的任务栈,在这种模式下,谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity的任务栈栈中,比如Acticity A启动了Activity B ,Activity B 是Standard模式,那么Activity B 就运行在Activity A的栈中,当我们用ApplicationContext区启动一个标准模式的Activity时,会报错,这是因为Standard模式的Activity默认进入启动它的Activity所在的任务栈中,而由于非Activity的Context(例如ApplicationContext)并没有所谓的任务栈,所以这就有问题了,解决这个问题的方法是为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位,这样启动的时候会为他创建一个新的任务栈,这个时候带启动的Activity实际上是以singleTask的模式启动的

(2) singleTop: 栈顶复用模式,这种模式下如果Activity已经位于任务栈的栈顶,那么此Activity不会重复创建,同时Activity的onNewIntent方法被回调,通过此方法的参数我们可以获取当前请求的信息,如果Activity已经存在但没有位于栈顶,那么Activity依然会重新创建

(3) singleTask:栈内复用模式,创建这样Activity的时候,首先会先确认他所需任务栈是否已经创建,否则先创建所需的任务栈,然后放入Activity,如果栈内已经有了Activity的实例那么,把这个Activity调到栈顶,同时回调onNewIntent方法,并且清除当前Activity上面所有的Activity

(4) singleInstance:加强版的sngletask,这种模式的Acticity只能单独处于一个任务栈中,后续请求都不需要重新创建Activity,除非这个任务栈被系统删除

清晰地描述下onNewIntent和onConfigurationChanged这两个生命周期方法的场景?

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);

这个方法会在singletop和singletask,singleInstance栈内已经存在atcivity,不在走onCreate,而会调用onNewIntent可以在这里处理intent传过来的数据
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
有的时候我们会在AndroidManifest.xml中加入这样的属性
android:configChanges="orientation| keyboard "
这个属性的意思是在改变屏幕方向不在调用onCreate而去调用onConfigurationChanged方法,如果不设置这个属性,改变屏幕方向会重复调用onCreate,造成重复初始化
}

任务栈

在singleTask中,经常提到Activity所需任务栈,那么他代表什么呢,这个要从一个参数说起:TaskAffinity可以翻译为任务相关性,这个参数标识了一个Activity所需要的任务栈的名字,默认情况下所有Activity所需任务栈名字为当前包名,当然我们还可以为每个Activity单独指定TaskAffinity,这个属性不能和包名相同,否则就相当于没有指定,TaskAffinity主要和singleTask启动模式或者allowTaskReparenting属性配对使用,在其他情况下没有意义,另外任务栈分为,前台任务栈和后台任务栈,后台任务栈中的Activity处于暂停状态,用户可以通过切换,把后台任务栈调到前台

当TaskAffinity和singleTask配对使用时,他是具有该模式的Activity的目前任务栈的名字,待启动Activity会运行在名字和TaskAffinity相同的任务栈中

当TaskAffinity和allowTaskReparenting结合使用时,这种情况比较复杂,会产生特殊效果,当一个应用A启动另一个应用B的某一个Activity时,如果这个Activity的allowTaskReparenting为true,那么应用B启动后,Activity会从应用A的任务栈转移到应用B 的任务栈,例如 应用A启动应用B的一个Activity C ,然后按home返回到桌面,然后单击应用B的桌面图标,这时候并不是启动的应用B的主Activity,而是显示已经被应用A启动的Activity C,或者说C从A的任务栈转移到了B的任务栈

如何给Activity指定启动模式,有两种方式

在manifest文件中
<activity
            android:name=".activity.ViewPagerActivity"
            android:launchMode="singleTask"/>
在代码中
Intent intent = new Intent(mContext, IPActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);

这俩种方式都可以为Activity指定启动模式,但是二者还是有区别的,优先级上,第二种优先级高于第一种,其次俩种限定范围上有所不同,比如第一种无法为Activity直接设定FALG_ACTIVITY_CLEAR_TOP,第二种无法为Activity指定singleInstance。

Activity 的 Flags

我们了解一些经常使用的标志位,其他不经常使用的自行了解

FLAG_ACTIVITY_NEW_TASK:

这个标记为是为Activity指定singleTask启动模式,其效果和在xml中指定相同

FLAG_ACTIVITY_SINGLE_TOP

这个标记为是为Activity指定singleTop启动模式,其效果和在xml中指定相同

FLAG_ACTIVITY_CLEAR_TOP:

此标记位的Activity,当他启动时,在同一个任务栈位于它上面的Activity都要出栈,如果Activity采用standard模式,那么连同他和上方都要出栈,系统创建新的实例,放入栈顶

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:

具有这个标记的Activity,不会出现在历史Activity的列表,当某些情况我们不希望用户通过历史列表返回Activity这个标记就比较有用,它等同于在xml中指定Activity的属性:android:excludeFromRecents =true

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值