请教高人,能说下activity四种启动模式的java四种引用应用场景景吗

Activity的启动模式 - 简书
下载简书移动应用
写了10655字,被9人关注,获得了5个喜欢
Activity的启动模式
LaunchMode
在声明Activity的xml中指定 android:launchMode="xxx"
标准模式。这是系统默认的模式,每次启动Activity都会重新创建一个新的Activity实例,也就是onCreate,onStart,onResume流程走一遍,并且一个任务栈里允许存在多个实例。
当我们使用ApplicationContext去启动Activity的时候,因为默认是standard模式会报错:Calling startActivity() from outside of an Activity
context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
因为standard 模式默认启动的Activity会和启动它的Activity在同一任务栈,而由于ApplicationContext非Activity的Context,并没有所谓的任务栈,所以提示我们需要使用FLAG_ACTIVITY_NEW_TASK来新建一个任务栈并把启动的Activity放进去。
栈顶复用模式。在同一个任务栈中栈顶如果有此Activity的实例,那么不会重新创建一个新实例,而是调用此Activity的onNewIntent,此时onCreate、onStart不会被调用。但如果此Activity在同一个任务栈但不在栈顶或之前用standard模式启动的,就会重新创建。
如ADBCD(第一个D不在栈顶则重新创建),ABCDD(第一个D为standard模式启动也会重新创建)。
singleTask
栈内复用模式。在同一个任务栈(注意:不一定是栈顶了)中如果有此Activity的实例,那么不会重新创建一个新实例,而是调用此Activity的onNewIntent,此时onCreate、onStart不会被调用。并且自带FLAG_ACTIVITY_CLEAR_TOP效果。
同一个栈内。如ADBC(要启动D,则把D挪到栈顶,BC由于clearTop而被移除栈,剩下AD)。如果D指定栈为S2,android:taskAffinity="S2",而启动它的Activity栈为S1,则先创建S2栈然后再new D放到S2中。
singleInstance
单例模式。这是一种加强的singleTask模式。除了singleTask模式所有特性外,它只能单独在一个任务栈中,跟其他Activity不能同时存在一个任务栈,整个Application也只有一个实例。
Intent的Flag
我们在代码里面通过Intent启动Activity的时候可以添加flag,如 :intent.addFlags(Intent.FLAG_ACTIVITY_XXX);
FLAG_ACTIVITY_BROUGHT_TO_FRONT
这个标志一般不是由程序代码设置的,如在launchMode中设置singleTask模式时系统帮你设定。
FLAG_ACTIVITY_CLEAR_TASK
此Activity将变成一个新Task中新的最底端的Activity,所有的之前此Activity实例和包含该实例的Task都会被关闭,这个标识仅仅和FLAG_ACTIVITY_NEW_TASK联合起来才能使用。
FLAG_ACTIVITY_NEW_TASK
与launchMode="singleTask"一样的效果。
FLAG_ACTIVITY_CLEAR_TOP
清除包含此Activity的Task中位于该Activity实例之上的其他Activity实例。这种行为的 launchMode 属性没有对应的值,只能通过代码设置。
单独使用的情况:ABCD 启动 B ,会销毁B和B以上的实例 变成 AB ,B 重新执行onCreate -& onStart配合FLAG_ACTIVITY_SINGLE_TOP使用,则 B 不会销毁只销毁B以上实例,然后B 执行onNewIntent -& onStart配合FLAG_ACTIVITY_NEW_TASK则是singleTask效果
FLAG_ACTIVITY_SINGLE_TOP
与launchMode="singleTop"一样的效果。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
设置了的话该Activity则不出现在最近使用的列表中。
FLAG_ACTIVITY_FORWARD_RESULT
如果A需要onActivityResult中获取返回结果,startActivityForResult B,而B只是过渡页,启动C之后就finish掉了,需要在 C 中setResult返回给A就可以用到这个标志。
A -& B -& XXXXX(无论多少个过渡页)
设置 FLAG_ACTIVITY_FORWARD_RESULT 来启动 C ,之后该XXX过渡页finish - & C
,那么C的结果返回给A
FLAG_ACTIVITY_NO_HISTORY
如果设置,新的Activity将不再历史stack中保留。用户一离开它,这个Activity就关闭了。例如A启动B的时候,给B设置了FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY,那么:
A -& B -& C ,启动C 就算 B没有自行finish ,也会变为 AC
FLAG_ACTIVITY_NO_ANIMATION
启动的时候不执行动画。
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
当用户点击Home,从历史中选择该Activity,系统会自动加上这个Flag。
FLAG_ACTIVITY_NO_USER_ACTION
在onPause()之前会调用onUserLeaving( )方法,如果使用了该标识,说明目标Activity不和用户交互,所以也就不需要回调onUserLeaving( )方法。
FLAG_ACTIVITY_REORDER_TO_FRONT
如果设置这个标记,新启动的Activity将会被放到它所属task的最前面例如,假如有一个Task包含4个Activity:A,B,C,D.如果D通过调用startActivity( )来启动B,如果使用了这个标记,B将会排在这个task的最上面,也即现在的顺序变成了A,C,D,B。如果使用了FLAG_ACTIVITY_CLEAR_TOP,这个标记将会被忽略。
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
如果设置该属性,并且这个Activity在一个新的Task中正在被启动或者被带到一个已经存在的Task的顶部,这时这个Task会被重置(即该Task中之前的Activity会被关闭),该Activity成为栈底第一个Activity。
FLAG_ACTIVITY_TASK_ON_HOME
把当前新启动的任务置于Home任务之上,也就是按back键从这个任务返回的时候会回到Home,即使这个不是他们最后看见的Activity。注意这个标记必须和FLAG_ACTIVITY_NEW_TASK加上android:taskAffinity一起使用。
FLAG_DEBUG_LOG_RESOLUTION
用来调试,当设置这个标志的时候,在解析这个intent的时候,将会打出打印信息(queryIntent函数)。
FLAG_INCLUDE_STOPPED_PACKAGES 和 FLAG_DEBUG_LOG_RESOLUTION
从Android 3.1开始,给Intent定义了两个新的Flag,分别为FLAG_INCLUDE_STOPPED_PACKAGES和FLAG_EXCLUDE_STOPPED_PACKAGES,用来控制Intent是否要对处于停止状态的App起作用,顾名思义:FLAG_INCLUDE_STOPPED_PACKAGES:表示包含未启动的AppFLAG_EXCLUDE_STOPPED_PACKAGES:表示不包含未启动的App值得注意的是,Android 3.1开始,系统向所有Intent的广播添加了FLAG_EXCLUDE_STOPPED_PACKAGES标志。这样做是为了防止广播无意或不必要地开启未启动App的后台服务。如果要强制调起未启动的App,后台服务或应用程序可以通过向广播Intent添加FLAG_INCLUDE_STOPPED_PACKAGES标志来唤醒。
FLAG_FROM_BACKGROUND
Intent不光可以在Acitivity里面start,还可以从service里面启动,这个参数就表示这个Intent是从后台服务发起的。
FLAG_GRANT_PERSISTABLE_URI_PERMISSION
区别于 FLAG_GRANT_READ_URI_PERMISSION 跟 FLAG_GRANT_WRITE_URI_PERMISSION, URI权限会持久存在即使重启,直到明确的用 revokeUriPermission(Uri, int) 撤销。 这个flag只提供可能持久授权。但是接收的应用必须调用ContentResolver的takePersistableUriPermission(Uri, int)方法实现 。
FLAG_GRANT_PERSISTABLE_URI_PERMISSION
Uri 权限授予任何原始授权URI前缀匹配的URI。
FLAG_GRANT_PERSISTABLE_URI_PERMISSION
结合FLAG_GRANT_READ_URI_PERMISSION 和 FLAG_GRANT_WRITE_URI_PERMISSION 使用。Uri 权限授予任何原始授权URI前缀匹配的URI。如果没有这个标志则必须精确匹配Uri了。
FLAG_GRANT_READ_URI_PERMISSION 和 FLAG_GRANT_WRITE_URI_PERMISSION
临时访问读权限和写权限 。Intent的接受者将被授予 INTENT 数据 uri 或者 在ClipData 上的读/写权限。
FLAG_RECEIVER_FOREGROUND
当发送广播时,允许其接受者 在前台运行的拥有更高的优先级,更短的超时间隔。
FLAG_RECEIVER_NO_ABORT
如果是有序广播,不要允许接收者中断广播播。
FLAG_RECEIVER_REGISTERED_ONLY
设置之后就不能通过xml来注册监听这个广播了,必须动态注册。
很多毒病程序为了证保自己被止终后可以再次行运,都会在xml中册注一些系统广播,妄图利用这些系统高频广播来实现自动启。
比如在老版本的android系统中,毒病程序可以通过监听TIME_TICK来动启自己的service后台行运,做一些秘隐的作工,而且就算自己被kill失落了,也能很快重新动启。
而一旦这些系统广播加了flag FLAG_RECEIVER_REGISTERED_ONLY,这些毒病程序就没辙了。
例如系统的TIME_TICK广播,由AlarmManagerService发送,我们看源码可以看到mTimeTickSender = PendingIntent.getBroadcast(context, 0,
new Intent(Intent.ACTION_TIME_TICK).addFlags(
Intent.FLAG_RECEIVER_REGISTERED_ONLY), 0);
这样就不能监听ACTION_TIME_TICK来自启动了。
FLAG_RECEIVER_REPLACE_PENDING
这个Flag 将会将之前的Intent 替代掉。加了这个Flag,在发送一系列的这样的Intent 之后,中间有些Intent 有可能在你还没有来得及处理的时候,就被替代掉了。
FLAG_ACTIVITY_NEW_DOCUMENT(原FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)
可以跟FLAG_ACTIVITY_MULTIPLE_TASK结合使用,当只用自己的时候相当于Manifast中 android.R.attr.documentLaunchMode="intoExisting",当跟FLAG_ACTIVITY_MULTIPLE_TASK 结合使用相当于 Manifast中android.R.attr.documentLaunchMode="always"。
FLAG_ACTIVITY_RETAIN_IN_RECENTS
默认情况下通过FLAG_ACTIVITY_NEW_DOCUMENT启动的Activity在关闭之后,Task中的记录会相对应的删除。如果为了能够重新启动这个Activity你想保留它,就可以使用者个flag,最近的记录将会保留在接口中以便用户去重新启动。接受该Flag的Activity可以使用autoRemoveFromRecents去复写这个request或者调用Activity.finishAndRemoveTask( )方法。
FLAG_ACTIVITY_MULTIPLE_TASK
这个标识用来创建一个新的task栈,并且在里面启动新的activity(所有情况,不管系统中存在不存在该activity实例),经常和FLAG_ACTIVITY_NEW_DOCUMENT或者FLAG_ACTIVITY_NEW_TASK一起使用。这上面两种使用场景下,如果没有带上FLAG_ACTIVITY_MULTIPLE_TASK标识,他们都会使系统搜索存在的task栈,去寻找匹配intent的一个activity,如果没有找到就会去新建一个task栈;但是当和FLAG_ACTIVITY_MULTIPLE_TASK一起使用的时候,这两种场景都会跳过搜索这步操作无条件的创建一个新的task。和FLAG_ACTIVITY_NEW_TASK一起使用需要注意,尽量不要使用该组合除非你完成了自己的顶部应用启动器,他们的组合使用会禁用已经存在的task栈回到前台的功能。
taskAffinity 和 allowTaskReparenting
taskAffinity用于指定当前Activity所关联的Task,allowTaskReparenting用于配置是否允许该Activity可以更换从属Task,通常情况二者连在一起使用,用于实现把一个应用程序的Activity移到另一个应用程序的Task中。allowTaskReparenting用来标记Activity能否从启动的Task移动到taskAffinity指定的Task,默认是继承至application中的allowTaskReparenting=false,如果为true,则表示可以更换;false表示不可以。
例如在A应用中启动了B应用的Activity,如果设置allowTaskReparenting=true,则Activity允许从A的Task移动到B的Task。但如果A被启动之后,Activity就会回到A的Task中。
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
选择支付方式:Android Activity 的四种启动模式 lunchMode
和 Intent.setFlags();
一. Activity 四种启动模式 lunchMode 在Manifest 配置文件中的属性如下:
(1) android:launchMode=&standard&
(2)android:launchMode=&singleTop&
(3)android:launchMode=&singleTask&
(4)android:launchMode=&singleInstance&
Android 中Activity 生命周期 跟Task 的关系,就是进栈出栈。
很多时候我们在Manifest的Activiy 配置信息中没有看到lunchMode 属性,其实没有配置这个属性就是默认属性 android:launchMode=&standard&。同一个工程AppA在这种模式下有AfirstActivity 启动 AsecondActivity,启动代码是:
& & & & & & & & Intent intent = new Intent();
intent.setClass(this, AsecondActivity.class);
startActivity(intent);
Log 打印如下:
两个TaskId 都是98.说明两个 activity 是在同一个 任务栈 Task 中。
接下来我们让这两个Activity 不在同一个Task 中。有两种方法实现:
(1)不修改启动代码,只修改 Mnaifest 中 给AsecondActivity 配置多添加 两行代码如下:
android:launchMode=&singleTask&
android:taskAffinity=&com.xjp&
(2)修改启动代码:
Intent intent = new Intent();
// ComponentName name = new
// ComponentName(&com.example.appa&,&com.example.appa.AsecondActivity&);
// intent.setComponent(name);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClass(this, AsecondActivity.class);
startActivity(intent);
多添加了一行
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
在修改 Mnaifest 中AsecondActivity 配置多添加一行
android:taskAffinity=&com.xjp&
看Log打印:
AfirstActivity taskId = 8 而 AsecondActivity TaskId = 9.所以两个 activity 不是在同一个任务栈 Task 中。虽然两个activity 是在同一个工程下面。
由此看出,代码里设置
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
和配置文件中设置
android:launchMode=&singleTask&
的效果是一样的。 但是请注意,这里要两个条件满足才 会让两个activity 不在同一个Task 中。必须 加上 属性
android:taskAffinity=&com.xjp&
有些人会奇怪,一般Manifest 配置文件中 很少看见 这个属性,这个属性的意思 是 &task 空间&=== &任务空间& 是的,当你没有设置的时候也是系统默认给设置 成为 当前应用的包名。我们这里设置 的和包名不一样。所以两个activity 的任务空间是不一样的,所以两个 activity 不在同一个 Task 中。 当然了,只是设置了
android:taskAffinity=&com.xjp&
android:launchMode=&singleTask&
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
两个 activity 也是在同一个任务空间的。亲测。
总结:当设置了
android:launchMode=&singleTask&
时,系统会查找 对应的
taskAffinity
任务空间是否 有启动过 这个activity ,如果没有启动,则在这个taskAffinity 任务空间启动,如果有启动过,则 将 这个activity 推送到栈顶, 那么在这个activity 之上的activity 都被推送出栈了,不在任务Task 中,也就是 Ondestroy 了。
三.当 配置文件中设置了 android:launchMode=&singleInstance&。不管 activity 怎么启动,都是在一个新的Task 任务中启动activity。
看Log 打印:
两个TaskId 不一样。并且 被启动的activity 唯一存在 新的任务队列中,也就是这个task 队列中只能有 一个activity。查看: 5686|回复: 4
context的startActivity启动Activity以及背后的Task和Activity栈
该用户从未签到主题帖子e币
本帖最后由 琴弦第七 于
12:10 编辑
关于直接使用Context的satartActivity需要加Intent.FLAG_ACTIVITY_NEW_TASK标识后发送Intent才能启动Activity,以及这个标识引起的一些问题。
因为做毕业设计,设计了个程序结构,想使用一个service提供统一的逻辑接口来统一管理整个程序所有的组件,以方便以后程序功能的扩展。本来是想让service作为程序的启动入口,但是这么一来Android系统的程序列表中就没有这个程序的图标,反而没办法启动程序,所以还是用一个Activity做程序启动入口。顺便把这个Activity作为程序启动画面,然后再由这个Activity启动一个Service,以后就由这个Service来统一管理整个程序所有的组件,包括启动Activity之类的。
为了方便后面的解释,先说一下我的测试程序用到的两个activity和一个service:
1、MainActivity,程序的启动入口,目的是显示启动画面后启动service,主要只有一个onCreate方法:
[mw_shl_code=java,true]public class MainActivity extends Activity {
& && &&&@Override
& && &&&protected void onCreate(Bundle savedInstanceState) {
& && && && && & super.onCreate(savedInstanceState);
& && && && && & setContentView(R.layout.activity_main);
& && && && && & new Handler().postDelayed(new Runnable(){
& && && && && && && && &@Override
& && && && && && && && &public void run() {
& && && && && && && && && && &&&Log.i(Tag.TAG, &MainActivity Handler:id=&+getTaskId());
& && && && && && && && && && &&&MainActivity.this.startService(new Intent(IntentAction.CORESERVICE));
& && && && && && && && && && &&&MainActivity.this.finish();
& && && && && && && && && && &&&MainActivity.this.overridePendingTransition(R.anim.logoin, R.anim.logoout);
& && && && && && && && &}}, 5000);
}[/mw_shl_code]
2、CoreService,这个service启动后由它管理整个程序,现在用它来启动一个Activity:
[mw_shl_code=java,true]& && &&&public int onStartCommand(Intent intent, int flags, int startId) {
& && && && && & Intent intent2 = new Intent(this,ExportFile.class);
& && && && && & startActivity(intent2);
& && && && && & return super.onStartCommand(intent, flags, startId);
& && &&&}[/mw_shl_code]
3、ExprotFile,是个普普通通的Activity,由service来启动的Activity。
用service来管理其他组件,比如启动activity,本来以为是一件简单的事情,直接使用context的startActivity方法(service继承context)就行了。类似于Activity中的用法,直接用new Intent(Context,Class)构造个Intent,然后用Service的startActivity发送,如上面CoreService代码中所述,但是就出现了以下异常:
根据这个异常的提示,大意就是无法启动CoreService,因为CoreService要启动Activity没有使用Intent.FLAG_ACTIVITY_NEW_TASK标识。按照异常提示的方法,修改CoreService启动Activity的代码,加多标识:
[mw_shl_code=java,true]& && &&&public int onStartCommand(Intent intent, int flags, int startId) {
& && && && && & Intent intent2 = new Intent(this,ExportFile.class);
intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
& && && && && & startActivity(intent2);
& && && && && & return super.onStartCommand(intent, flags, startId);
& && &&&}[/mw_shl_code]
毫无意外,service就能正常的启动一个Activity了。为什么Activity的startActivity不需要添加Intent.FLAG_ACTIVITY_NEW_TASK,而除了Activity之外的其它直接使用Context的startActivity方法就需要添加这个标识?
Activity的startActivity方法对Context的startActivity方法进行了重写,使其能够直接启动一个Activity,但是其它继承Context的组件没有,因此需要使用Intent.FLAG_ACTIVITY_NEW_TASK这个标识。那么这个标识会导致什么结果?从这个标识上看,两个关键单词:new task。因此,先来了解一下task是什么东东。
我们搞的都知道在Android里面,有一个叫Activity栈来管理Activity的东西,其实这个东西就是task,task以栈先进后出的管理方式来管理其中的Activity。每当一个程序启动的时候,android系统就会为这个程序创建一个task来管理这个程序用到的activity。从我们使用Android的体验来看,当我们打开一个程序,并进入这个程序的多个Activity之后,通过返回键就能够返回这个程序的上一个Activity,直到返回home,这就是因为task将这些activity以栈的方式管理导致的,task里面的activity栈返回到底变空了就回到了home。如果此时还没有回到桌面(task里的activity栈还没有空),就按home键回到桌面,启动了另一个程序,并且进入了这个程序中的多个activity,同样在这个程序中也可以用返回键返回上一个activity,直到桌面,但是却不会返回到之前那个程序,这说明两个程序使用的task不是同一个task。证明这个结论的另一个现象是此时再按home键回到桌面,再次单击第一个程序的图标进入程序,就会发现回到了第一程序按home键时的那个activity,而且还能够继续使用返回键返回。
需要注意的是,虽然一个程序启动的时候系统会为这个程序创建一个task供其使用,但是一个程序的task里面可以包含的activity也可以是非本程序的activity。比如我们经常遇到的打开了一个应用,这个应用里面有个电话号码,点击后可以调用系统拨号程序界面等待拨号,但是此时突然又不想打这个电话,就按了返回键,界面又回到了我们的应用,而不是home。可以看出在点击电话号码后,拨号程序拨号界面的activity被加入到我们应用的task里面。
文字有点多了,小结一下:一个程序启动后系统会为这个程序分配一个task供其使用,另外同一个task里面可以拥有不同应用程序的activity。那么,同一个程序能不能拥有多个task?这就涉及到加载activity的四种模式:standard、singleTop、singleTask、singleInstance。可以在AndroidManifest.xml中activity标签的属性launchMode中设置该activity的加载模式。简述下这四种模式的区别:
1、standard模式:默认的模式,以这种模式加载必定会构造一个新的Activity实例放到目标task中的activity栈顶,不管当前task的栈顶是什么情况。
2、singleTop模式:这种模式与standard模式类似,区别在于加载activity会多个判断步骤。判断需要加载的新activity与当前task栈顶的activity是不是同一个,相同的话就不再构造新的activity,并调用这个activity的newInstance()方法,不相同就还是会构造新的activity放到栈顶。
3、singleTask模式:这种模式下,会创建一个新的task来加载这个activity,并且这个task中只允许存在一个Activity的一个实例(以后可以加载其他activity的实例)。
4、singleTask模式:这种模式下,会创建一个新的task,并且这个task中只能存在一个需要加载的这个Activity实例,即除了这个activity之外,不允许其他activity。
从这四种Activity的加载模式中大概可以看出同一个程序可以拥有多个task。
是时候回到使用Intent.FLAG_ACTIVITY_NEW_TASK标识会有什么影响这个一开始的问题了。每一个task都有一个affinity属性,或者应该说每一个activity都有一个affinity属性,而task的affinity属性由task的根activity决定,这个affinity用来标识一个task,可以看做是一个task的id。activity的affinity属性可以在AndroidManifest.xml中的activity或者application标签(application标识application下所有的activity)的属性android:taskAffinity中设置。这个属性的属性值是一个字符串,默认情况下会使用继承元素的包名作为属性值。使用Intent.FLAG_ACTIVITY_NEW_TASK标识的时候,会先查看需要加载activity的affinity属性值。如果当前不存在相同affinity的task,那么就会创建一个新的task来加载这个activity。如果当前已经存在相同affinity的task,那么就不创一个新的,而是根据这个activity的加载模式加载到已存在的这个task中。
以下来验证一下这个结论,分别在activity中添加打印task id的方法:
1、MainActivity:
[mw_shl_code=java,true]public class MainActivity extends Activity {
& && &&&@Override
& && &&&protected void onCreate(Bundle savedInstanceState) {
& && && && && & super.onCreate(savedInstanceState);
& && && && && & setContentView(R.layout.activity_main);
& && && && && & new Handler().postDelayed(new Runnable(){
& && && && && && && && &@Override
& && && && && && && && &public void run() {
& && && && && && && && && && &&&Log.i(Tag.TAG, &MainActivity Handler:id=&+getTaskId());&&//打印ID
& && && && && && && && && && &&&MainActivity.this.startService(new Intent(IntentAction.CORESERVICE));
& && && && && && && && && && &&&MainActivity.this.finish();
& && && && && && && && && && &&&MainActivity.this.overridePendingTransition(R.anim.logoin, R.anim.logoout);
& && && && && && && && &}}, 5000);
}[/mw_shl_code]
2、ExportFile:
[mw_shl_code=java,true]public class ExportFile extends Activity {
& && &&&@Override
& && &&&protected void onCreate(Bundle savedInstanceState) {
& && && && && & // TODO Auto-generated method stub
& && && && && & super.onCreate(savedInstanceState);
& && && && && & setContentView(R.layout.activity_main);
& && && && && & Log.i(Tag.TAG, &ExportFile onCreate:id=&+getTaskId());&&//打印task ID
[/mw_shl_code]
运行后打印的日志:
发现打印出来的id不一样?我没有修改过AndroidManifest.xml中两个activity的testaffinity属性,属性值应该都是默认的包名。那么MainActivity启动的时候就应该分配到一个task,并且这个task的affinity属性由MainActivity的affinity属性值(也就是元素所在包名)决定,那么由Coreservice使用Intent.FLAG_ACTIVITY_NEW_TASK启动ExportFile这个Activity时,ExportFile的affinity值与MainActivity相同,应该不会重新建一个task才对。
导致这个问题的原因在于,我的代码中MainActivity启动CoreService之后,使用finish把自己给结束掉了,此时MainActivity所在的task已经空。当CoreService启动ExportFile时,虽然有个空的task,但是task的affinity由根Activity的affinity属性决定,所以当前已经找不到与ExportFile相同affinity属性的task,系统就会重新创建一个task导致了id的变化。
验证这个结论,MainActivity的finish语句注释掉,运行后打印日志:
可以看到id已经相同了,证明两个Activity都在同一个task里面,我按了返回键后也能回到MainActivity。
呼~打了两个多钟字,终于写完了。以上结论纯属个人琢磨结果,如有错误,欢迎指正,感激不尽。
参考资料:
/ghj1976/archive//2032495.html
http://blog.csdn.net/ghj1976/article/details/6371549
本帖子中包含更多资源
才可以下载或查看,没有帐号?
非常支持LZ的原创精神~
该用户从未签到主题帖子e币
這樣多得好得東西~~一定要學習~~也給大大按個贊
签到天数: 35 天连续签到: 1 天[LV.5]常住居民I主题帖子e币
好棒。。。学习喽~
该用户从未签到主题帖子e币
对于activity的几种launchMode LZ 还可看下
对于其他blog 来说 在天朝 不就是你抄我 , 我抄你,
曾经碰到一个问题 ,原始blog错了 结果导致N个blog全部错。
所以看 这个官网解释是最好的。
而且每个人看 这个英文都有自己的一个解释。呵呵&&没事可以看看
哈哈,好!我努力读读英文,感谢指导。&
该用户从未签到主题帖子e币
sk. 发表于
对于activity的几种launchMode LZ 还可看下 /guide/topics/manifest/activity ...
哈哈,好!我努力读读英文,感谢指导。
圣诞限量勋章
圣诞限量勋章
社区认证会员
社区认证会员
QQ已认证,此人靠谱
推荐阅读热门话题
619621774549410403309264253251246245245232231715
半小时前2&小时前2&小时前2&小时前3&小时前4&小时前4&小时前4&小时前4&小时前4&小时前5&小时前6&小时前6&小时前14&小时前14&小时前15&小时前
Powered by

我要回帖

更多关于 java四种引用应用场景 的文章

 

随机推荐