弱龄寄事外,委怀在琴书。这篇文章主要讲述Android:图解四种启动模式 及 实际应用场景讲解相关的知识,希望能为你提供帮助。
在一个项目中会包含着多个Activity,
系统中使用任务栈来存储创建的Activity实例,
任务栈是一种“后进先出”的栈结构。举个栗子,
若我们多次启动同一个Activity,
系统会创建多个实例依次放入任务栈中,
当按back键返回时,
每按一次,
一个Activity出栈,
直到栈空为止,
当栈中无任何Activity,
系统就会回收此任务栈。
上面这个例子中的Activity并没有设置启动模式,
你会发现多次启动同一个Activity,
而系统却创建了多个实例,
白白浪费内存,
这种情况android早就替我们考虑好了。Android为Activity 的创建提供了4种启动模式,
而根据实际应用场景的不同,
为Activity 选择不同的启动模式,
最大化减少了每次都需要在栈中创建一个新的Activity的压力,
减少内存使用。
启动模式的具体说明和使用场景?
下面根据这篇博文来一一解惑。
一. Android启动模式详解
文章图片
1. Standard 标准模式 说明: Android创建Activity时的默认模式, 如果没有为Activity设置启动模式的话, 默认为标准模式。每次启动一个Activity都会重新创建一个新的实例入栈, 不管这个实例是否存在。
生命周期: 如上所示, 每次被创建的实例Activity 的生命周期符合典型情况, 它的onCreate、onStart、onResume都会被调用。
举例: 此时Activity 栈中以此有A、B、C三个Activity, 此时C处于栈顶, 启动模式为Standard 模式。若在C Activity中添加点击事件, 需要跳转到另一个同类型的C Activity。结果是另一个C Activity进入栈中, 成为栈顶。
文章图片
2. SingleTop 栈顶复用模式 说明: 分两种处理情况: 需要创建的Activity已经处于栈顶时, 此时会直接复用栈顶的Activity, 不会再创建新的Activity; 若需要创建的Activity不处于栈顶, 此时会重新创建一个新的Activity入栈, 同Standard模式一样。
生命周期: 若情况一中栈顶的Activity被直接复用时, 它的onCreate、onStart不会被系统调用, 因为它并没有发生改变, 但是一个新的方法 onNewIntent会被回调( Activity被正常创建时不会回调此方法) 。
举例: 此时Activity 栈中以此有A、B、C三个Activity, 此时C处于栈顶, 启动模式为SingleTop 模式。情况一: 在C Activity中添加点击事件, 需要跳转到另一个同类型的C Activity。结果是直接复用栈顶的C Activity。情况二: 在C Activity中添加点击事件, 需要跳转到另一个A Activity。结果是创建一个新的Activity入栈, 成为栈顶。
文章图片
3. SingleTask 栈内复用模式 说明: 若需要创建的Activity已经处于栈中时, 此时不会创建新的Activity, 而是将存在栈中的Activity上面的其它Activity全部销毁, 使它成为栈顶。
生命周期: 同SingleTop 模式中的情况一相同, 只会重新回调Activity中的 onNewIntent方法
举例: 此时Activity 栈中以此有A、B、C三个Activity, 此时C处于栈顶, 启动模式为SingleTask 模式。情况一: 在C Activity中添加点击事件, 需要跳转到另一个同类型的C Activity。结果是直接用栈顶的C Activity。情况二: 在C Activity中添加点击事件, 需要跳转到另一个A Activity。结果是将A Activity上面的B、C全部销毁, 使A Activity成为栈顶。
文章图片
4. SingleInstance 单实例模式 说明: SingleInstance比较特殊, 是全局单例模式, 是一种加强的SingleTask模式, 它除了具有它所有特性外, 还加强了一点: 具有此模式的Activity只能单独位于一个任务栈中。这个常用于系统中的应用, 例如Launch、锁屏键的应用等等, 整个系统中只有一个! 所以在我们的应用中一般不会用到, 了解即可。
举例: 比如 A Activity是该模式, 启动A后, 系统会为它创建一个单独的任务栈, 由于栈内复用的特性, 后续的请求均不会创建新的Activity, 除非这个独特的任务栈被系统销毁。
二.启动模式的使用方式 1. 在 Manifest.xml中指定Activity启动模式 一种静态的指定方法, 在Manifest.xml文件中声明Activity的同时指定它的启动模式, 这样在代码中跳转时会按照指定的模式来创建Activity。例子如下:
<
activity android:name=
"
..activity.MultiportActivity"
android:launchMode=
"
singleTask"
/>
2. 启动Activity时, 在Intent中指定启动模式去创建Activity 一种动态的启动模式, 在new 一个Intent后, 通过Intent的addFlags方法去动态指定一个启动模式。例子如下:
Intent intent =
new Intent();
intent.setClass(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
【Android(图解四种启动模式 及 实际应用场景讲解)】注意: 以上两种方式都可以为Activity指定启动模式, 但是二者还是有区别的。
( 1) 优先级: 动态指定方式即第二种比第一种优先级要高, 若两者同时存在, 以第二种方式为准。
( 2) 限定范围: 第一种方式无法为Activity直接指定 FLAG_ACTIVITY_CLEAR_TOP 标识, 第二种方式无法为Activity指定 singleInstance 模式。
三. Activity 的 Flags 标记位既可以设定Activity的启动模式, 如同上面介绍的, 在动态指定启动模式, 比如 FLAG_ACTIVITY_NEW_TASK 和 FLAG_ACTIVITY_SINGLE_TOP 等。它还可以影响Activity 的运行状态 , 比如 FLAG_ACTIVITY_CLEAN_TOP 和 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 等。下面介绍几个主要的标记位, 切勿死记, 理解几个即可, 需要时再查官方文档。
1. FLAG_ACTIVITY_NEW_TASK
作用是为Activity指定 “SingleTask”启动模式, 跟在AndroidMainfest.xml指定效果相同。
2. FLAG_ACTIVITY_SINGLE_TOP
作用是为Activity指定 “SingleTop”启动模式, 跟在AndroidMainfest.xml指定效果相同。
3. FLAG_ACTIVITY_CLEAN_TOP
具有此标记位的Activity, 启动时会将与该Activity在同一任务栈的其它Activity出栈, 一般与SingleTask启动模式一起出现。它会完成SingleTask的作用, 但其实SingleTask启动模式默认具有此标记位的作用
4.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具有此标记位的Activity不会出现在历史Activity的列表中, 使用场景: 当某些情况下我们不希望用户通过历史列表回到Activity时, 此标记位便体现了它的效果。它等同于在xml中指定Activity的属性:
android:excludeFromRecents=
"
trure"
四. 启动模式的实际应用场景 这四种模式中的Standard模式是最普通的一种, 没有什么特别注意, 而SingleInstance模式是整个系统的单例模式, 在我们的应用中一般不会应用到, 所以, 这里就具体讲解 SingleTop 和 SingleTask模式的运用场景:
1. SingleTask模式的运用场景 最常见的应用场景就是保持我们应用开启后只有一个Activity的实例, 最典型的例子就是应用中展示的主页( Home页) 。假设用户在主页跳转到其它页面, 执行多次操作后想返回到主页, 如果不使用SingleTask模式, 在点击返回的过程中会多次看到主页, 这明显就是设计不合理了。
2. SingleTop模式的运用场景 如果你在当前的Activity中又要启动同类型的Activity, 此时建议将此类型Activity的启动模式指定为SingleTop, 可以减少Activity的创建, 节省内存!
3. 注意: 复用Activity时的生命周期回调 这里还需要考虑一个Activity跳转时携带页面参数的问题。
因为当一个Activity设置了SingleTop或者SingleTask模式后, 跳转此Activity出现复用原有Activity的情况时, 此Activity的onCreate方法将不会再次执行! onCreate方法只会在第一次创建Activity时被执行。
而一般onCreate方法中会进行该页面的数据初始化、UI初始化, 如果页面的展示数据无关页面跳转传递的参数, 则不必担心此问题, 若页面展示的数据就是通过getInten() 方法来获取, 那么问题就会出现: getInten()获取的一直都是老数据, 根本无法接收跳转时传送的新数据! 下面, 通过一个例子来详解:
Manifest.xml
<
activity
android:name=
"
.activity.CourseDetailActivity"
android:launchMode=
"
singleTop"
android:screenOrientation=
"
portrait"
/>
public class CourseDetailActivity extends BaseActivity{
......
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_course_detail_layout);
initData();
initView();
}//初始化数据
private void initData() {
Intent intent =
getIntent();
mCourseID =
intent.getStringExtra(COURSE_ID);
}//初始化UI
private void initView() {
......
}
......
}
以上代码中的CourseDetailActivity在配置文件中设置了启动模式是SingleTop模式, 根据上面启动模式的介绍可得知, 当CourseDetailActivity处于栈顶时, 再次跳转页面到CourseDetailActivity时会直接复用原有的Activity, 而且此页面需要展示的数据是从getIntent() 方法得来, 可是initData()方法不会再次被调用, 此时页面就无法显示新的数据。
当然这种情况系统早就为我们想过了, 这时我们需要另外一个回调 onNewIntent( Intent intent) 方法, 此方法会传入最新的intent, 这样我们就可以解决上述问题。这里建议的方法是重新去setIntent, 然后重新去初始化数据和UI, 代码如下所示:
/*
* 复用Activity时的生命周期回调
*/
@
Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
initData();
initView();
}
这样, 在一个页面中可以重复跳转并显示不同的内容。
启动模式其实是初学Android时会学到的知识点, 以前也是一知半懂, 有些知识点其实跟设计模式一样, 你不去使用而只是学习并非可以掌握到精髓, 只有真正去使用才会将这些变成你自己的, 文章部分内容参考了《Android开发艺术探索》, 好书推荐。
最近在使用启动模式, 特此来小小总结一番, 网上关于此类的文章也有许多, 但是多总结总结还是有益无害的。
欢迎指错~
希望对你们有帮助 : )
推荐阅读
- 安卓7.0遇到 android.os.FileUriExposedException: file:///storage/emulated.. exposed beyond app through In
- android 四则运算
- 简单的Android四则运算
- 有瑕疵的Android四则运算
- Frameworks detected: Android framework is detected in the project
- Android 6.0版本以后运行时权限提醒
- Android的学习总结
- android 编译打包烧录
- Android 软键盘控制方法以及开发中遇到的一些问题。转