standard模式(默认):只要创建了Activity实例,一旦激活该Activity,则会向任务栈中加入新创建的实例,退出Activity则会在任务栈中销毁该实例。
singleTop模式: 如果激活的Activity实例处于栈顶则无需重新创建新的实例,会重用已存在的实例,否则会在任务栈中创建新的实例。
singleTask模式:
1. 寻找相同taskaffinity的Task,如果没有寻找到,则新启动一个Task,并且把该Activity放置到底部
2. 如果存在相同的taskaffinity,那么再查询TaskStack中是否存在已经实例化的Activity,如果存在,则清空该Activity上面的所有Activity,最后调用
newIntent(), 否则新创建一个Activity放入Task中
singleInstance模式: Activity单独在一个taskStack中。如果已经存在则调用newIntent(),否则新创建一个放入单独的taskStack中。
在开发中经常会使用onActivityResult,来处理Activity之间的数据返回,使用该方法,有几个关键点:
1. 传递数据的时候,两个Activity必须在同一个Task Stack中,所以最好保证两个Activity都使用standard的启动模式。
2.调用startActivityForResult的时候,requestCode必须大于0。
3.返回的时候,注意使用setResult来设置返回值,且统一使用RESULT_OK等标准代码点来设置执行状态
FLAG_ACTIVITY_NEW_TASK : 如果taskaffinity指向的TaskStack不存在,则新创建一个。
FLAG_ACTIVITY_CLEAR_TOP : 清空要跳转Activity上面所有的Activity实例。
FLAG_ACTIVITY_SINGLE_TOP:和singleTop启动模式类似。
在项目中,遇到了需要像微信一样管理Activity,即实现效果如下:
假设App中有Main Activity(Root),Chat Activity,以及 Other Activity 三个Activity,其中Main Activity 在位于栈底,且为启动Activity
1. App内,无论从哪里进入ChatActivity,Back回去都进入Main Activity
2. 从HOME进入App,都为最后进入的Activity
3. 从通知栏进入App,都默认进入Chat Activity
为了实现效果1,通常有两种方法,
1. 修改Chat Activity 的Back方法,生成一个 Intent FLAG : SINGLE_TOP | CLEAR_TOP 标记的Intent,这样子,通过这个Intent启动MainActivity,会清空MainActivity上面所有的Activity。
2. 启动Chat Activity的的Intent中,直接添加 Intent FLAG : SINGLE_TOP | CLEAR_TOP ,从Main Activity启动,这样子在启动Chat Activity的时候,直接清空Main Activity上面所有的Activity,然后从Main startActivity(Chat Activity);
实现这个的效果,最重要的是,不使用特殊的启动模式,singleTask,singleInstance(未测试),可以使用singleTop,standard模式
这个效果实现的方法,和实现效果1类似,不过需要添加NEW_TASK 这种Intent Flag。然而,如果我们把三种效果混合在一起,可能就遇到如下的问题。
从通知进入ChatActivity,然后点击HOME按钮,进入程序列表页面,然后再点击App的ICON,进入App,这时候,我们发现效果2无法实现,而是新建了MainActivity,点击Back按钮,进入的页面是之前的ChatActivity,相当于AC栈为 MainActivity->ChatActivity->MainActivity.
为什么会遇到这个问题? 进过搜索资料以及实验,得出如下的结论:
1. 当Main Activity 的launchMode为singleTask, singleInstance(未测试) 的时候,通常不创建新的MainActivity
2. 当Main Activity的launchMode为standard,或者为signleTop的时候,则按照 栈顶的Activity(也就是Main Activity)的action 和category 是否和androidManifest.xml中的
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
一致,如果非一致,则创建新的Main Activity,否则就是简单的AC栈移动到前台。为了解决这个问题,我们只需要在启动MainActivity的时候,添加
intent.setAction(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); 当然为了能直接使用Context.startActivity 使用Intent,可以统一添加
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);