startActivityForResult中回调setResult注意事项.以及Task认识

本文探讨了在Android开发中使用startActivityForResult进行页面间数据传递时的注意事项,强调了请求码应大于等于0,并指出setResult()应在finish()前调用。在Android不同版本上可能存在行为差异,一种解决方法是使用广播。同时,文章讲解了Activity的四种启动模式:standard、singleTop、singleTask和singleInstance,并通过实例展示了如何通过Intent.FLAG_ACTIVITY_NEW_TASK影响Activity的Task归属。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:

1.startActivityForResult的请求码要大于等于0

2.activity返回result是在被finish的时候,也就是说调用setResult()方法必须在finish()之前
那么如果在如下方法中调用setResult()也有可能不会返回成功: onPause(), onStop(), onDestroy(),
因为这些方法调用不一定是在finish之前的,当然在onCreate()就调用setResult肯定是在finish之前的。

在APP开发中,为了在页面之间传递对象(这里强调回传),我们通常使用startActivityForResult。如果ActivityA要跳转到ActivityB,但是ActivityB的启动模式为singleTop,方法调用就会存在一些“异样”。在Android4.4,ActivityA调用startActivityForResult后,ActivityB会立即执行;but在安卓5.0上,就不存在该问题。探究了一种该问题的解决方法,使用广播。这里就要注意了要在onCreate&&onDestory中进行注册和注销,否则接收不到信息哦!

3. setResult()界面 不能设置其他启动模式 ,否则可能会报错

二:启动模式

Activity有四种加载模式:standard(默认), singleTop, singleTask和 singleInstance。

Task 栈
1.  Standard  默认加载模式   ,创建时
不管栈中是否已经创建Activity实例,每次启动都会创建新的Acitivty实例
android:launchMode="standard" 
如:现在栈的情况为:A B C D,在D这个Activity中通过Intent跳转到D,那么现在的栈情况为: A B C D D 。此时如果栈顶的D通过Intent跳转到B,则栈情况为:A B C D D B。此时如果依次按返回键,D  D C B A将会依次弹出栈而显示在界面上。
2.SingleTop 栈顶单实例创建时
a.栈中没有创建Activtiy实例,就创建一个新的Activity实例
b.如果该Activtiy实例处于栈顶,就不会创建新的Activtiy实例
c.如果处于栈中,启动就会创建新的Activtiy实例
 android:launchMode="SingleTop "
例如:现在栈的情况为:A B C D。D的Launch mode设置成了singleTop,那么在D中启动Intent跳转到D,那么将不会新创建一个D的实例压入栈中,此时栈的情况依然为:A B C D。但是如果此时B的模式也是singleTop,D跳转到B,那么则会新建一个B的实例压入栈中,因为此时B不是位于栈顶,此时栈的情况就变成了:A B C D B。
3.SingleTask栈中单实例,创建时
a.栈中没有创建该Activtiy实例,就创建一个新的Activity实例
b.如果该Activtiy实例处于栈顶,启动不会创建新的Activtiy实例
c.处于栈中,销毁该Acitvity之上的其他实例,本身不会创建新的实例
 android:launchMode="SingleTask"
例如:现在栈的情况为:A B C D。B的Launch mode为singleTask,此时D通过Intent跳转到B,则栈的情况变成了:A B。而C和D被弹出销毁了,也就是说位于B之上的实例都被销毁了。
情况二:如果ActivityB由另外一个程序启动:假设apkA是情况一中的应用,apkB是另外一个测试程序,在apkB中启动apkA中的ActivityB,再分两种情况,如果ActivityB未启动过,ActivityB会位于栈底,是根元素,会启动新的task;如果ActivityB启动过,则ActivityB保持原来的位置不变,在栈底或者栈顶,移除掉ActivityB之上所有的activity(如果有),
注意singleTask模式的Activity不管是位于栈顶还是栈底,再次运行这个Activity时,都会destory掉它上面的Activity来保证整个栈中只有一个自己,切记切记
注意:startActivityFoResult();  有可能接收不到B界面的返回值

4.SingleInstance全局单实例
a.不存在,创建新的Task,存放Activity实例
b.已经存在,下次启动,不会创建新的Activity,新的Task,存放Activity实例,移到前台
singleInstance:将Activity压入一个新建的任务栈中。例如:Task栈1的情况为:A B C。C通过Intent跳转到D,而D的Launch mode为singleInstance,则将会新建一个Task栈2。此时Task栈1的情况还是为:A B C。Task栈2的情况为:D。此时屏幕界面显示D的内容,如果这时D又通过Intent跳转到D,则Task栈2中也不会新建一个D的实例,所以两个栈的情况也不会变化。而如果D跳转到C,则栈1的情况变成了:A B C C,因为C的Launch mode为standard,此时如果再按返回键,则栈1变成:A B C。也就是说现在界面还显示C的内容,不是D。
//获得Activity所在的栈的Id
Log.e("AActivity", "TaskId"+getTaskId());

标志位Flag
FLAG_ACTIVITY_SINGLE_TOP    类似栈顶单实例
Intent intent = new Intent(this, MainActivity.class);
//标志位  为目标界面设置   加载模式   
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);

FLAG_ACTIVITY_CLEAR_TOP
销毁本身,以及在它之上的Activtiy,然后会创建新的Activity实例

FLAG_ACTIVITY_NEW_TASK
在Service BroadcastReceiver(onReceiver()) 跳转界面  需要为跳转的界面设置
标志位FLAG_ACTIVITY_NEW_TASK
Task学习初认:
task是一个具有栈结构的容器,可以放置多个Activity实例。启动一个应用,系统就会为之创建一个task,来放置根Activity;默认情况下,一个Activity启动另一个Activity时,两个Activity是放置在同一个task中。系统task和task之间是互相独立的。
affinity:affinity对于Activity来说就好像它的身份证一样,可以告诉所在的task,自己属于这个task中的一员;拥有相同affinity的多个Activity理论同属于一个task,task自身的affinity决定于根Activity的affinity值。2.启动一个Activity过程中Intent使用了FLAG_ACTIVITY_NEW_TASK标记,根据affinity查找或创建一个新的具有对应affinity的task。我们会在后面进行详细讲解。默认情况下,一个应用内的所有Activity都具有相同的affinity,都是从Application(参考<application>的taskAffinity属性)继承而来,而Application默认的affinity是<manifest>中的包名,我们可以为<application>设置taskAffinity属性值,这样可以应用到<application>下的所有<activity>,也可以单独为某个Activity设置taskAffinity。
Intent常见flags:
Activity的taskAffinity属性进行匹配,如果找到一个task的taskAffinity与之相同,就将目标Activity压入此task中,如果查找无果,则创建一个新的task,并将该task的taskAffinity设置为目标Activity的taskActivity,将目标Activity放置于此task。注意,如果同一个应用中Activity的taskAffinity都使用默认值或都设置相同值时,应用内的Activity之间的跳转使用这个标记是没有意义的,因为当前应用task就是目标Activity最好的宿主。下面我们会通过实例进行演示这个特性:

我们新建两个项目,分别命名为appA和appB,并且分别创建FirstActivity和SecondActivity,我们准备让appB中的FirstActivity跳转到appA的SecondActivity。appA中的SecondActivity配置如下:

[html]  view plain  copy
  1. <activity android:name=".SecondActivity">  
  2.             <intent-filter>  
  3.                 <action android:name="android.intent.action.APP_A_SECOND_ACTIVITY" />  
  4.                 <category android:name="android.intent.category.DEFAULT" />  
  5.             </intent-filter>  
  6.         </activity>  
然后,在appB中的FirstActivity跳转代码如下:

[java]  view plain  copy
  1. Intent intent = new Intent("android.intent.action.APP_A_SECOND_ACTIVITY");  
  2. startActivity(intent);  
我们要演示几个步骤:1.在appB中的FirstActivity点击按钮跳转到appA中的SecondActivity;2.按Home键回到主屏,在主选单中再次启动appB;3.按Home键回到主屏,在主选单中启动appA。演示过程如图所示:



再次启动appB应用:


启动appA应用:


我们发现在从appB跳转到appA的SecondActivity之后,SecondActivity实例好像是嵌入到了appB中,但是不影响appA的正常运行,这种关系如下图所示:不是设置Intent.FLAG_ACTIVITY_NEW_TASK默认会压倒同一个栈空间


然后我们修改一下跳转的代码:

[java]  view plain  copy
  1. Intent intent = new Intent("android.intent.action.APP_A_SECOND_ACTIVITY");  
  2. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  3. startActivity(intent);  
我们加上了FLAG_NEW_TASK标记,在来看一下演示结果:



再次启动appB:


启动appA:


我们看到差别了吧,当我们再次启动appB时已经看不到刚才启动的appA中的SecondActivity,而启动appA时却直接看到了,说明这个SecondActivity实例并不在appB的task内,而是创建了一个task,这个task的affinity就是SecondActivity默认的affinity,由于appA的SecondActivity的affinity是从Application继承而来,所以当appA启动时会直接找到这个task,而不是创建新的task。我们看一下解析图:






评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值