Android Activity的加载模式和onActivityResult方法之间的冲突

摘要:
前言今天调试程序时,发现单击活动上的返回键将调用该活动的onActivityResult()方法。因为之前其他活动的LaunchMode是Normal,所以没有特殊设置。由于需要,此活动已更改为singleTop。通过在Google上搜索androidactivityonactivityresultingTop,探索发现了一些问题。例如,如果开发人员将Activity设置为singleTask模式,onActivityResult将不会收到任何结果。事实上,我使用了singTop,但onActivityResult仍然被无故调用。当Activty退出时,将根据给定的requestCode调用onActivityResult()方法。这是为了避免跳转到另一个活动时可见的闪烁。

前言

今天在调试程序时,发现在某一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 CasesLaunch ModeMultiple Instances?Comments
Normal launches for most activities"standard"YesDefault. The system always creates a new instance of the activity in the target task and routes the intent to it.
"singleTop"ConditionallyIf 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"NoThe 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"NoSame 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方法之间的冲突》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇redhat7查看系统版本 修改主机名CSS在线字体库,外部字体的引用方法@font-face下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

android 在manifest 中设置 多个Activity时的 默认 根 Activity

An <activity> element can also specify various intent filters—using the <intent-filter> element—in order to declare how other application components may activate it. W...

&amp;lt;Android Framework 之路&amp;gt;Android5.1 MediaScanner

前言 MediaScanner是Android系统中针对媒体文件的扫描过程,将储存空间中的媒体文件通过扫描的方式遍历并存储在数据库中,然后通过MediaProvider提供接口使用,在Android多媒体中占有很重要的位置。 源码位置 packagesprovidersmediaprovider frameworksasemediajavaandroi...

广播、应用Android BroadcastReceiver(一)by小雨

每日一贴,今天的内容关键字为广播、应用- Android BroadcastReceiver 分析: broadcastReceiver是android的四大件组之一,大部分的广播是统系收回来的。例如,屏幕闭关,电池电量缺乏等等。应用一样可以建创广播,例如:当下载成完的时候,要让其他的应用道知这个情况,要需用到broadcastreceiver,recei...

unity 游戏第一次安装完之后运行,切出来,点击桌面图标后黑屏问题

unity 游戏第一次安装完之后运行,切出来,点击桌面图标后黑屏问题 这个问题只会在第一次出现,之后就是桌面进入了,不会再出现这个问题了 这是一个解决办法吧: 就是将安装之后运行的游戏杀死,然后在重新进入游戏,  // 在onCreate()最前面添加一下代码 if (!isTaskRoot()) { final Intent intent = g...

android环境下的即时通讯

首先了解一下即时通信的概念。通过消息通道 传输消息对象,一个账号发往另外一账号,只要账号在线,可以即时获取到消息,这就是最简单的即使通讯。消息通道可由TCP/IP UDP实现。通俗讲就是把一个人要发送给另外一个人的消息对象(文字,音视频,文件)通过消息通道(C/S实时通信)进行传输的服务。即时通讯应该包括四种形式,在线直传、在线代理、离线代理、离线扩展。在...

Android程序开发学习笔记系列——基础篇(附源码)

  随着Android的越炒越热和各种应用的不断推出,自己也比较巧合的在去年12月份宽带续费时给送了个电信的Android系统定制机——算是促使我提前了Android开发的学习计划,并给我提供了一个开发测试的'场地'(手机),也更增强了我学习Android程序开发的兴趣——别的市场前景等先暂且不说,至少我学会了,可以做个程序自己用。闲话少说,Android程...