显示意图跳转Activity
val intent = Intent(this, Activity2::class.java)
startActivity(intent)
隐式意图跳转Activity
- 在Manifest中添加
<intent-filter>
<action android:name="com.mypotota.studyactivit.ACTIVITY_2"/> //添加意图
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
- 在Activity中添加
val intent = Intent()
//设置跳转意图
intent.setAction("com.mypotota.studyactivit.ACTIVITY_2")
intent.addCategory(Intent.CATEGORY_DEFAULT)
startActivity(intent)
通过显示意图跳转第三方应用
val intent = Intent()
// intent.setClassName("com.android.settings","com.android.settings.Settings")
val componentName = ComponentName("com.android.settings", "com.android.settings.Settings")
intent.setComponent(componentName)
startActivity(intent)
通过隐式意图跳转第三方应用
val intent = Intent()
//需要知道 第三方应用的Action
intent.setAction(Intent.ACTION_WEB_SEARCH)
intent.setPackage("mark.via")
intent.addCategory(Intent.CATEGORY_DEFAULT)
startActivity(intent)
任务栈
什么是任务栈
任务栈就是通过一个栈的数据结构来管理一系列任务,实际上,这里的任务指的就是Activity,任务栈就是管理Activity切换的 任务栈记录了Activity之间的调用和启动顺序,当我们按下返回键时,就可以根据任务栈里的信息来决定返回到哪个窗口
看到这里,有人可能会觉得,任务栈不就是一个List就能解决的事情,第N个Activity销毁,返回到第N-1个Activity就是了 其实这样想也算对了那么一点点,因为栈说白了就是弹出N,露出N-1,但是这仅仅是任务栈最简单的形式
实际上,应用并不一定就是当前窗口返回上个窗口,还可能在返回前销毁一些已经无效的窗口 而且,应用还可能是多进程的,或者被其它进程调用启动,这些都不是一个List能够解决的
任务栈的新特性
- 打开一个新的Activity后,新的Activity会被存放到栈顶位置,只有栈顶的Activity才可以与用户进行交互
- 栈顶的Activity结束后,界面会回退到任务栈中的上一个Activity
- 当一个任务栈中的Activity全部结束,无Activity可以继续回退时,会销毁此任务栈,并回退到最近一次访问的任务栈的栈顶
- 系统桌面,即Launcher程序,也是一个独立的任务栈,当我们从桌面进入到自己的任务栈,任务栈结束后就会回到桌面
- 当我们按下Home键(圆形按钮)或任务键(方形按钮)时,实际上是打开了Launcher程序,等于进入了Launcher任务栈一次
- 任务栈是由操作系统管理的,它并不属于某个应用或进程
- Launcher程序通过桌面图标启动了一个新Activity,Launcher程序通过通知栏启动了一个新Activity,旧的Activity启动一个SingleInstance模式的Activity,旧的Activity启动了一个指定了taskAffinity属性的Activity,旧的Activity启动了一个documentLaunchMode="always"的Activity,旧的Activity启动Activity时指定了FLAG_ACTIVITY_NEW_TASK选项,都会创建一个新的任务栈
- 除了这些情况之外,一个Activity启动另一个Activity,这两个Activity都是处于同一个任务栈中的,即便是多进程应用,或者调用其它应用中的Activity组件,也是处于同一任务栈的
综上所述,我们大概知道,一个应用可以包含多个任务栈,一个任务栈也可以包含来自不同应用的Activity,主要看这些Activity是不是通过相互调用启动的,只有通过Launcher程序启动,或者指定了特殊模式的Activity,才会创建一个新的任务栈
获取任务栈的相关信息
操作系统处于安全考虑,只允许我们获取和当前应用相关的任务栈
这里的相关,指的任务栈由当前应用创建,如果其它应用启动了我们的共享组件,只能在其它应用中获取该组件相关的任务栈信息
方法一:这个API只能获取到最近任务列表中的任务栈
后台任务栈必须开启了android:documentLaunchMode="always",出现在最近任务列表中,才能获取到
//获取任务栈列表
ActivityManager activityManager = getSystemService(ActivityManager.class);
List<ActivityManager.AppTask> tasks = activityManager.getAppTasks();
//遍历任务栈
for (ActivityManager.AppTask task : tasks) {
ActivityManager.RecentTaskInfo info = task.getTaskInfo();
int taskId = info.id; //任务栈ID
Intent launchIntent = info.baseIntent; //创建该任务栈的Intent
String action = launchIntent.getAction(); //Intent的action
Set<String> categories = launchIntent.getCategories(); //Intent的category
ComponentName component = launchIntent.getComponent(); //Intent要启动的组件名,即Activity的包名和类名
Bundle extras = launchIntent.getExtras(); //Intent携带的额外参数
int activityCount = info.numActivities; //栈内Activity数量
String topActivity = info.topActivity.getClassName(); //栈顶Activity
String baseActivity = info.baseActivity.getClassName(); //栈底Activity,如果所有Activity都不销毁,baseActivity就是originActivity
boolean isRunning = info.isRunning; //任务栈是否在运行,Activity有可能处于挂起状态,等待restore,该API安卓10开始才可用
task.moveToFront(); //调度任务栈至前台显示
task.setExcludeFromRecents(true); //不显示在最近任务列表中
task.finishAndRemoveTask(); //销毁任务栈内全部Activity
task.startActivity(context, intent, options); //在指定任务栈中启动一个新的Activity,并将当前任务栈调至前台
}
方法二:能获取应用全部的任务栈,但是接口没有上面的灵活
//获取任务栈列表
ActivityManager manager = getSystemService(ActivityManager.class);
List<ActivityManager.RunningTaskInfo> infos = manager.getRunningTasks(100);
//遍历任务栈
for (ActivityManager.RunningTaskInfo info : infos) {
int taskId = info.id;
int activityCount = info.numActivities;
ComponentName baseActivity = info.baseActivity;
ComponentName topActivity = info.topActivity;
manager.moveTaskToFront(taskId, 0);
break;
}
Activity 的启动模式
任务栈最简单的管理方式就是,每次启动Activity都在当前栈新建一个Activity实例,放到栈顶
但这个方式并不能适合所有情景,因此安卓提供了几种常用的任务栈管理方式,即Activity的启动模式,这个属性可以在Manifest清单中通过launchMode属性配置
Standard模式,默认的模式,总是在当前任务栈中创建一个新的Activity实例SingleTop模式,如果栈顶已存在目标Activity的实例,则复用,否则新建一个新的实例SingleTask模式,如果栈中已存在目标Activity的实例,则复用,同时清除此Activity顶部的其它ActivitySingleInstance模式,单例模式,开启一个独立的任务栈,专门存放目标类型的Activity,并且只允许一个对象实 例,已存在则复用。如果SingleInstance模式的Activity启动了其它类型的Activity,如果没有特别设定,被启动的 Activity将会被存放到Standard任务栈中SingleTask模式适合作为程序的启动入口,回到入口时,其它Activity全部销毁SingleInstance模式适合与程序独立,或者供多个应用共享的界面
几种特殊启动模式的应用场景
-
SingleTop模式
比如我们使用一款视频APP观看短视频,视频播放页面同时还推荐了类似视频
当我们点击了推荐视频,事件顺序大概是:打开视频播放页面 - 点击推荐视频 - 复用当前页面播放推荐视频,同时刷新推荐列表
即栈顶对象可复用,没必要新建一个实例 -
SingleTask模式
比如我们使用一款购物APP购买商品,Activity打开顺序大概是:商品页面 - 下单页面 - 支付页面 - 交易完成界面 显然,我们完成时,需要返回商品页面,没必要返回支付页面,因为订单已经结束,因此我们需要在回到商品页面时销毁下单和支付页面 即Activity顶部的任务已过期,没必要再保留
-
SingleInstance模式
比如我们使用系统自带的相机应用,由于性能和硬件占用的原因,肯定是不允许同时打开两份的 当我们进去相机开始录像,再去其它应用里面逐个逛一遍,然后回到桌面再点击相机图标,肯定是会回到之前的实例里继续录制,而不是新建一个新的实例,也不能销毁改Activity顶部的其它Activity 即客观条件只允许单例,但栈结构并不允许复用栈中间的对象,只能复用栈顶对象( SingleTop),或者先弹出复用对象顶部的其它对象,让目标对象浮到栈顶再复用(SingleTask),所以SingleInstance模式只能自己独占一个任务栈