startActivityForResult不回调的问题
2016-03-31 14:00
381 查看
大家都知道,可以通过使用 startActivityForResult() 和 onActivityResult() 方法来传递或接收参数。
但你是否遭遇过onActivityResult()不执行或者未按预想的那样执行的情况呢?
源码的startActivityForResult(Intent intent,int requestCode)的requestCode说明是 :
If >= 0, this code will be returned in onActivityResult() when the activity exits.
源码是这样的:
Using a negative requestCode is the same as calling
* {@link #startActivity} (the activity is not launched as a sub-activity).
进入这个方法startActivity(Intent intent, Bundle bundle):
于是我就看出为什么了,RESULT_OK在Activity中的值就是-1,所以如果我们给的请求码是-1的时候是就相当于使用startActivity(),这样是不会调用onActivityForResult方法的。
API里面也有说明:startActivityForResult(Intent intent, int requestCode, Bundle options)的注释里有一段话是这样说的:
Note that this method should only be used with Intent protocols
* that are defined to return a result. In other protocols (such as
* {@link Intent#ACTION_MAIN} or {@link Intent#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.
发生这种情况的深层原因呢,在http://developer.android.com/guide/components/tasks-and-back-stack.html文档里也有说明:
在下图中,存在着前两个栈,其中直接显示在屏幕上与用户交互的Back Stack,及另一个隐藏在后台的Background Task,该栈栈顶的Activity Y其launchMode为singleTask。
如果在Activity 2中调用BackgroundTask中已经启动过的Activity Y,则Background Task内占据屏幕并且该Task下所有的栈都会保留当前的栈位置及顺序push进Back Task形成新的结构,顺序由上至下为Activity Y→Activity X→Activity 2→Activity 1。
在Activity Y界面按返回键,则ActivityY出栈,Activity X占据屏幕!注意,由Activity2调用的Activity Y,但返回键后,回退显示的是Activity
X!所以即使在Activity Y执行setResult(),Activity 2也是无法接收到的。更通俗的讲就是:standard 模式的Activity 2 startActivityForResult(new Intent(Activity 2,Activity Y.class), requestCode);其中Activity
Y是singleTask,然后Activity Y再设置setResult(resultCode);,这样的话,Activity 2的onActivityResult(int requestCode, int resultCode, Intent data)很可能接收不到数据。
继续按返回键,则才回到Activity 2。
在这种Tasks的入栈与出栈设计下,由于可能有Activity X的存在,所以在Activity 2启动Activity Y时,则直接回调了onActivityResult()并给出了RESULT_CANCEL也就可以理解了。
但你是否遭遇过onActivityResult()不执行或者未按预想的那样执行的情况呢?
一、requestCode 小于0
两个activity传递数据和返回数据时,请求方的onActivityResult始终无响应,通过debug调试模式也没见调用该方法。查看了各种配置和程序代码,均未发现有错误之处。阅读API才发现requestCode >= 0才起作用。有时使用Activity.RESULT_OK,一样不回调,也是因为.RESULT_OK = -1。源码的startActivityForResult(Intent intent,int requestCode)的requestCode说明是 :
If >= 0, this code will be returned in onActivityResult() when the activity exits.
源码是这样的:
/** * Same as calling {@link #startActivityForResult(Intent, int, Bundle)} * with no options. * * @param intent The intent to start. * @param requestCode If >= 0, this code will be returned in * onActivityResult() when the activity exits. * * @throws android.content.ActivityNotFoundException * * @see #startActivity */ public void startActivityForResult(Intent intent, int requestCode) { startActivityForResult(intent, requestCode, null); }重要的是这一句:如果用负值的requestCode和调用startActivity是一样的,所以代码不走startActivityForResult而是startActivity
Using a negative requestCode is the same as calling
* {@link #startActivity} (the activity is not launched as a sub-activity).
/** * 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 * {@link #startActivity} (the activity is not launched as a sub-activity). * * <p>Note that this method should only be used with Intent protocols * that are defined to return a result. In other protocols (such as * {@link Intent#ACTION_MAIN} or {@link Intent#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. * * <p>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. * * <p>This method throws {@link android.content.ActivityNotFoundException} * if there was no Activity found to run the given Intent. * * @param intent The intent to start. * @param requestCode If >= 0, this code will be returned in * onActivityResult() when the activity exits. * @param options Additional options for how the Activity should be started. * See {@link android.content.Context#startActivity(Intent, Bundle) * Context.startActivity(Intent, Bundle)} for more details. * * @throws android.content.ActivityNotFoundException * * @see #startActivity */ public void startActivityForResult(Intent intent, int requestCode, Bundle options) {}
/** * Same as {@link #startActivity(Intent, Bundle)} with no options * specified. * * @param intent The intent to start. * * @throws android.content.ActivityNotFoundException * * @see {@link #startActivity(Intent, Bundle)} * @see #startActivityForResult */ @Override public void startActivity(Intent intent) { startActivity(intent, null); }
进入这个方法startActivity(Intent intent, Bundle bundle):
/** * Launch a new activity. You will not receive any information about when * the activity exits. This implementation overrides the base version, * providing information about * the activity performing the launch. Because of this additional * information, the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag is not * required; if not specified, the new activity will be added to the * task of the caller. * * <p>This method throws {@link android.content.ActivityNotFoundException} * if there was no Activity found to run the given Intent. * * @param intent The intent to start. * @param options Additional options for how the Activity should be started. * See {@link android.content.Context#startActivity(Intent, Bundle) * Context.startActivity(Intent, Bundle)} for more details. * * @throws android.content.ActivityNotFoundException * * @see {@link #startActivity(Intent)} * @see #startActivityForResult */ @Override public void startActivity(Intent intent, Bundle options) { if (options != null) { startActivityForResult(intent, -1, options); } else { // Note we want to go through this call for compatibility with // applications that may have overridden the method. startActivityForResult(intent, -1); } }
于是我就看出为什么了,RESULT_OK在Activity中的值就是-1,所以如果我们给的请求码是-1的时候是就相当于使用startActivity(),这样是不会调用onActivityForResult方法的。
二、 launchMode为singleTask或者singleInstance
通过startActivityForResult()方式去启动launchMode=singleTask或者的Activity,onActivityResult()会被立即回调且resultCode值为RESULT_CANCEL。API里面也有说明:startActivityForResult(Intent intent, int requestCode, Bundle options)的注释里有一段话是这样说的:
Note that this method should only be used with Intent protocols
* that are defined to return a result. In other protocols (such as
* {@link Intent#ACTION_MAIN} or {@link Intent#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.
发生这种情况的深层原因呢,在http://developer.android.com/guide/components/tasks-and-back-stack.html文档里也有说明:
在下图中,存在着前两个栈,其中直接显示在屏幕上与用户交互的Back Stack,及另一个隐藏在后台的Background Task,该栈栈顶的Activity Y其launchMode为singleTask。
如果在Activity 2中调用BackgroundTask中已经启动过的Activity Y,则Background Task内占据屏幕并且该Task下所有的栈都会保留当前的栈位置及顺序push进Back Task形成新的结构,顺序由上至下为Activity Y→Activity X→Activity 2→Activity 1。
在Activity Y界面按返回键,则ActivityY出栈,Activity X占据屏幕!注意,由Activity2调用的Activity Y,但返回键后,回退显示的是Activity
X!所以即使在Activity Y执行setResult(),Activity 2也是无法接收到的。更通俗的讲就是:standard 模式的Activity 2 startActivityForResult(new Intent(Activity 2,Activity Y.class), requestCode);其中Activity
Y是singleTask,然后Activity Y再设置setResult(resultCode);,这样的话,Activity 2的onActivityResult(int requestCode, int resultCode, Intent data)很可能接收不到数据。
继续按返回键,则才回到Activity 2。
在这种Tasks的入栈与出栈设计下,由于可能有Activity X的存在,所以在Activity 2启动Activity Y时,则直接回调了onActivityResult()并给出了RESULT_CANCEL也就可以理解了。
相关文章推荐
- Centos安装mongodb
- Ubuntu系统下搭建Python开发环境
- android mediarecorder自制录相机花屏问题
- SQL:不存在则insert存在则update
- -生成树的相关问题
- Android动画 Animation
- 1394 ( Minimum Inversion Number ) (线段树)
- poj1743:Musical Theme(后缀数组)
- Java 中的悲观锁和乐观锁的实现
- 重构代码,解决商城加载太慢总结
- kafka总结
- iOS
- FZU 2122 ——又见LKity——————【KMP字符串匹配】
- Hive与HBase区别
- Java怎么获取多网卡本地ip
- ios 指定返回的跳转页面
- iOS纯代码开发和xib开发
- MySQL日志管理
- HttpClient连接池使用demo
- A. Round House