前言

今天在调试程序时,发现在某一Activity上点击返回键会调用该Activity的onActivityResult()方法。我一开始用log,后来用断点跟踪调试半天,还是百思不得其解。因为之前其他的Activity的LaunchMode都是Normal,没有特殊设定,这个Activity由于需求改成了singleTop。直到我确定没有一个地方是代码主动触发的,我才想到了跟Activity的LaunchMode是否有关。

探索

在Google上搜索android activity onactivityresult singTop找到了一些问题。


stackoverflow

stackoverflow上有些人跟我遇到的问题类似。比如说有一位开发者把Activity设置成了singleTask模式,onActivityResult就收不到任何结果了。当他把singleTask模式改回标准模式,又恢复正常。

这个问题下面给出的答案中,有一位说startActivityForResult的文档中有这么一句话:

For example, if the activity you are launching uses the singleTask launch mode, it will not run in your task and thus you will immediately receive a cancel result.

意思是:比如说,如果你正加载的activity使用了singleTask的加载模式,它不会在你的栈中运行,而且这样你会马上收到一个取消的结果。

即在onActivityResult里马上得到一个RESULT_CANCEL.

他还补充说没有很好的补救方法。可以试试用监听广播的方法。

另一个stackoverflow的问题中,有人直接回答了不能再singleInstance或singleTop模式下使用startActivityForResult()方法,不仅被采纳了,票数还不低。

剩下的一个stackoverflow问题中,有人说把singleTask改成singleTop就会正常,得到高达59票并被采纳。实际上我用的就是singTop,可是onActivityResult还是无缘无故被调用了。


startActivityForResult的文档:

public void startActivityForResult (Intent intent, int requestCode, Bundle options)

Added in API level 16

Launch an activity for which you would like a result when it finished. When this activity exits, your onActivityResult() method will be called with the given requestCode. Using a negative requestCode is the same as calling startActivity(Intent) (the activity is not launched as a sub-activity).

加载一个Activity,当它结束时你会得到结果。当这个Activty退出了,你的onActivityResult()方法会根据给出的requestCode被调用。使用一个负的requestCode和调用startActivity(intent)一样(activity不被加载成子activity)

Note that this method should only be used with Intent protocols that are defined to return a result. In other protocols (such as ACTION_MAIN or ACTION_VIEW), you may not get the result when you expect. For example, if the activity you are launching uses the singleTask launch mode, it will not run in your task and thus you will immediately receive a cancel result.

注意这个方法只能用于被定义要返回结果的Intent协议。在其他协议中(譬如ACTION_MAIN或ACTION_VIEW),你可能在你想得到结果时得不到。比如,当你正载入的Activity使用的singleTask加载模式,它不会在你的栈中运行,这样你会立马得到一个取消的结果。

As a special case, if you call startActivityForResult() with a requestCode >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your activity, then your window will not be displayed until a result is returned back from the started activity. This is to avoid visible flickering when redirecting to another activity.

有一个特例是,当你在初始的onCreate()方法或onResume()方法中用一个大于等于0的请求码调用startActivityForResult(),你的窗口在被启动的Activity返回结果前不会显示。这是为了避免跳转到另一Activity时可见的闪烁。

This method throws ActivityNotFoundException if there was no Activity found to run the given Intent.

如果运行所给Intent的Activity没被找到,该方法会抛出ActivityNotFoundException异常。


Activity的加载模式

Use Cases Launch Mode Multiple Instances? Comments
Normal launches for most activities "standard" Yes Default. The system always creates a new instance of the activity in the target task and routes the intent to it.
"singleTop" Conditionally If an instance of the activity already exists at the top of the target task, the system routes the intent to that instance through a call to itsonNewIntent() method, rather than creating a new instance of the activity.
Specialized launches
(not recommended for general use)
"singleTask" No The system creates the activity at the root of a new task and routes the intent to it. However, if an instance of the activity already exists, the system routes the intent to existing instance through a call to itsonNewIntent() method, rather than creating a new one.
"singleInstance" No Same as "singleTask", except that the system doesn't launch any other activities into the task holding the instance. The activity is always the single and only member of its task.

singleTop模式,可用来解决栈顶多个重复相同的Activity的问题。

singleTask模式和后面的singleInstance模式都是只创建一个实例的。

当intent到来,需要创建singleTask模式Activity的时候,系统会检查栈里面是否已经有该Activity的实例。如果有直接将intent发送给它。

singleInstance模式解决了这个问题(绕了这么半天才说到正题)。让这个模式下的Activity单独在一个task栈中。这个栈只有一个Activity。导游应用和google地图应用发送的intent都由这个Activity接收和展示。

总结

后来我改变了onActivityResult里面ResultCode为RESULT_OK时刷新界面的具体实现方法,可是onActivityResult还是会自己被调用,只是暂时没触发任何bug,可它还是个定时炸弹啊。

以后在选择Activity的加载模式时,要考虑onActivtyResult方法与之存在冲突。

参考

  1. http://stackoverflow.com/questions/8960072/onactivityresult-with-launchmode-singletask
  2. http://developer.android.com/reference/android/app/Activity.html#startActivityForResult%28android.content.Intent,%20int%29
  3. http://stackoverflow.com/questions/7910840/android-startactivityforresult-immediately-triggering-onactivityresult
  4. http://stackoverflow.com/questions/3354955/onactivityresult-called-prematurely
 

Android Activity的加载模式和onActivityResult方法之间的冲突的更多相关文章

  1. [转]Android Activity的加载模式和onActivityResult方法之间的冲突

    前言 今天在调试程序时,发现在某一Activity上点击返回键会调用该Activity的onActivityResult()方法.我一开始用log,后来用断点跟踪调试半天,还是百思不得其解.因为之前其 ...

  2. 我的Android进阶之旅------>Android Activity的singleTask加载模式和onActivityResult方法之间的冲突

    今天调试一个bug的时候,情景如下: 一个Activity A,需要用startActivityForResult方法开启Activity B.Activity B的launch mode被设置为si ...

  3. Android四种Activity的加载模式(转)

    建议首先阅读下面两篇文章,这样才可以更好的理解Activity的加载模式: Android的进程,线程模型: http://www.cnblogs.com/ghj1976/archive/2011/0 ...

  4. Android四种Activity的加载模式

    建议首先阅读下面两篇文章,这样才可以更好的理解Activity的加载模式: Android的进程,线程模型 http://www.cnblogs.com/ghj1976/archive/2011/04 ...

  5. Activity的加载模式及Intent.setFlags

    在多Activity开发中,有可能是自己应用之间的Activity跳转,或者夹带其他应用的可复用Activity.可能会希望跳转到原来某个Activity实例,而不是产生大量重复的Activity. ...

  6. ANDROID基础ACTIVITY篇之Activity的加载模式

    在这之前首先让我们先了解一下什么是Task Task,简单的说,就是一组以栈的模式聚集在一起的Activity组件集合.它们有潜在的前后驱关联,新加入的Activity组件,位于栈顶,并仅有在栈顶的A ...

  7. Android Activity的加载的模式

    ---恢复内容开始--- 本文来自http://www.cnblogs.com/lwbqqyumidi/p/3771542.html launchMode在多个Activity跳转的过程中扮演着重要的 ...

  8. 在主Android Activity中加载Fragment的一般简易方法 ,来模拟一个微信界面。

    在Fragment的生命周期中,需要重点关注onCreate.onCreateView.onViewCreated.Activity与Fragment生命周期在设计模式上大体一致. package c ...

  9. Android使用glide加载.9图片的方法

    我们在开发过程中会经常使用.9图片, 因为它可以使图片拉伸的时候,保证其不会失真. 而我们把.9图片放在服务器端,通过glide直接加载,会报错. 我们的解决方法是 通过sdk的aapt工具 把.9图 ...

随机推荐

  1. Android应用字体更改

    首先下载字库 中华字体网 然后在项目的assets目录下建立文件夹fonts.将字体库文件xxx.ttf放入 然后使用下面工具类,自定义控件自己注意添加 public class TypefaceTo ...

  2. 酷友观点/经验:支付接口返回数据接收地址,session数据丢失(或者说失效)的问题浅析(原创文章)

    酷友观点/经验:支付接口返回数据接收地址,session数据丢失(或者说失效)的问题浅析(原创文章)   最近手头在开发一个游戏官网,在支付模块采用神州付技术支持,神州付数据表单中要求提供服务器返回地 ...

  3. laravel redis

    安装配置redis服务器 $ wget http://download.redis.io/releases/redis-3.0.5.tar.gz $ tar xzf redis-.tar.gz $ c ...

  4. 使用apache.lang包安全简洁地操作Java时间

    引言 最近偶遇apache开发的工作java工具包,一使用,就发现自己爱上它了.不多说了,下面介绍org.apache.commons.lang3.time包中处理java程序员为之头疼的时间的类. ...

  5. 【C++】类型转换(学习笔记)

    1. 隐式类型转换,相关联的类型(e.g.int vs double)之间可以发生隐式类型转换. 比如,在条件中,非布尔类型转为布尔类型: 初始化时,初始值变为变量类型: 赋值时,右值变成左侧的类型: ...

  6. centos升级支持到C++11, gcc4.8.2

    升级到4.8[这个应该是目前最新的啦,不过网上查的话已经到5.2啦,感觉落后一点比较稳,当然还有就是这个版本是新的里面使用最多的] wget http://people.centos.org/tru/ ...

  7. 【转修正】sql server行版本控制的隔离级别

    在SQL Server标准的已提交读(READ COMMITTED)隔离级别下,一个读操作会和一个写操作相互阻塞.未提交读(READ UNCOMMITTED)虽然不会有这种阻塞,但是读操作可能会读到脏 ...

  8. 20145320 《Java程序设计》第5周学习总结

    20145320 <Java程序设计>第5周学习总结 教材学习内容总结 8.1 语法与继承架构 try.catch Java中的错误会被包装为对象,而使用try与catch,JVM会执行t ...

  9. Oracle 正则表达式函数-REGEXP_REPLACE 使用例子

    原文在这: 戳 REGEXP_REPLACE 6个参数 第一个是输入的字符串 第二个是正则表达式 第三个是替换的字符 第四个是标识从第几个字符开始正则表达式匹配.(默认为1) 第五个是标识第几个匹配组 ...

  10. Android requires compiler compliance level 5.0 or 6.0. Found '1.7' instead

    Android requires compiler compliance level 5.0 or 6.0. Found '1.7' instead 在解决问题Underscores can only ...