面试时被问到一个问题:Activity A通过startActivityForResult()启动Activity B,在B没有被finish()之前,A的onActivityResult()就返回了失败的结果。为什么会出现这种情况?
两个相关的方法
- startActivityForResult()
- onActivityResult()
一般我们是这样使用,在MainActivity.java中
public static final int REQUEST_CODE=1001;
...
public void click(View view){
Intent intent=new Intent(MainActivity.this,NewActivity.class);
intent.putExtra("msgA","我是蛮大人");
startActivityForResult(intent,REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i(TAG, "MainActivity onActivityResult");
if (requestCode==REQUEST_CODE&&resultCode==RESULT_OK){
String msg=data.getStringExtra("msgB");
Log.i(TAG, "onActivityResult: msgB="+msg);
}
}
在NewActivity.java中
public void click(View view){
Intent data=new Intent();
data.putExtra("msgB","哇咔咔");
setResult(RESULT_OK,data);
finish();
}
我们看下Activity.java
/**
* @param requestCode If >= 0, this code will be returned in
* onActivityResult() when the activity exits.
**/
public void startActivityForResult(Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
方法注释提到中参数requestCode需要大于或等0,这里会出现第一个问题:onActivityResult()方法不会被调用?
答:参照 使用正确的RequestCode,requestCode使用-1或者[0,65536)中的某一个int值时不会报错,但是使用-1时,onActivityResult()不会被调用。
继续看 Activity.java API
/**1、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.
* 2、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.
**/
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
...
}
对于注释中提到的第一点,如果将要启动的Activity启动模式是singleTask,会立即回调onActivityResult()。
测试1,在AndroidManifest.xml配置
<activity android:name=".NewActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
结果如下:
//进入MainActivity
04-15 00:06:34.777 29915-29915/com.example.testing.activityresulttest I/Activity_Test: MainActivity onCreate
04-15 00:06:34.777 29915-29915/com.example.testing.activityresulttest I/Activity_Test: MainActivity onStart
04-15 00:06:34.777 29915-29915/com.example.testing.activityresulttest I/Activity_Test: MainActivity onResume
//点击button进入NewActivity
04-15 00:06:59.867 29915-29915/com.example.testing.activityresulttest I/Activity_Test: MainActivity onPause
04-15 00:06:59.927 29915-29915/com.example.testing.activityresulttest I/Activity_Test: NewActivity onCreate: msgA=我是蛮大人
04-15 00:06:59.927 29915-29915/com.example.testing.activityresulttest I/Activity_Test: NewActivity onStart
04-15 00:06:59.927 29915-29915/com.example.testing.activityresulttest I/Activity_Test: NewActivity onResume
04-15 00:07:00.427 29915-29915/com.example.testing.activityresulttest I/Activity_Test: MainActivity onStop
//点击button关闭NewActivity
04-15 00:19:28.320 29915-29915/com.example.testing.activityresulttest I/Activity_Test: NewActivity onPause
04-15 00:19:28.330 29915-29915/com.example.testing.activityresulttest I/Activity_Test: MainActivity onActivityResult
04-15 00:19:28.330 29915-29915/com.example.testing.activityresulttest I/Activity_Test: onActivityResult: msgB=哇咔咔
04-15 00:19:28.330 29915-29915/com.example.testing.activityresulttest I/Activity_Test: MainActivity onRestart
04-15 00:19:28.330 29915-29915/com.example.testing.activityresulttest I/Activity_Test: MainActivity onStart
04-15 00:19:28.330 29915-29915/com.example.testing.activityresulttest I/Activity_Test: MainActivity onResume
04-15 00:19:28.660 29915-29915/com.example.testing.activityresulttest I/Activity_Test: NewActivity onStop
04-15 00:19:28.660 29915-29915/com.example.testing.activityresulttest I/Activity_Test: NewActivity onDestroy
可以看到,并不会立即回调onActivityResult()。
测试2,在代码中配置
//AndroidManifest.xml
<activity android:name=".NewActivity"/>
<!--<activity android:name=".NewActivity"-->
<!--android:launchMode="singleTask">-->
<!--<intent-filter>-->
<!--<action android:name="android.intent.action.VIEW"/>-->
<!--<category android:name="android.intent.category.DEFAULT"/>-->
<!--</intent-filter>-->
<!--</activity>-->
---------------------------------------------------
//MainActivity.java
public void click(View view) {
Intent intent=new Intent(MainActivity.this, NewActivity.class);
//add for test
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("msgA","我是蛮大人");
startActivityForResult(intent, REQUEST_CODE);
}
结果如下:
//进入MainActivity
04-15 00:29:36.480 26905-26905/com.example.testing.activityresulttest I/Activity_Test: MainActivity onCreate
04-15 00:29:36.480 26905-26905/com.example.testing.activityresulttest I/Activity_Test: MainActivity onStart
04-15 00:29:36.480 26905-26905/com.example.testing.activityresulttest I/Activity_Test: MainActivity onResume
//点击button进入NewActivity
04-15 00:29:51.390 26905-26905/com.example.testing.activityresulttest I/Activity_Test: MainActivity onPause
04-15 00:29:51.390 26905-26905/com.example.testing.activityresulttest I/Activity_Test: MainActivity onActivityResult
04-15 00:29:51.390 26905-26905/com.example.testing.activityresulttest I/Activity_Test: MainActivity onResume
04-15 00:29:51.400 26905-26905/com.example.testing.activityresulttest I/Activity_Test: MainActivity onPause
04-15 00:29:51.440 26905-26905/com.example.testing.activityresulttest I/Activity_Test: NewActivity onCreate: msgA=我是蛮大人
04-15 00:29:51.450 26905-26905/com.example.testing.activityresulttest I/Activity_Test: NewActivity onStart
04-15 00:29:51.450 26905-26905/com.example.testing.activityresulttest I/Activity_Test: NewActivity onResume
04-15 00:29:51.970 26905-26905/com.example.testing.activityresulttest I/Activity_Test: MainActivity onStop
//点击button关闭NewActivity
04-15 00:30:23.690 26905-26905/com.example.testing.activityresulttest I/Activity_Test: NewActivity onPause
04-15 00:30:23.700 26905-26905/com.example.testing.activityresulttest I/Activity_Test: MainActivity onRestart
04-15 00:30:23.700 26905-26905/com.example.testing.activityresulttest I/Activity_Test: MainActivity onStart
04-15 00:30:23.700 26905-26905/com.example.testing.activityresulttest I/Activity_Test: MainActivity onResume
04-15 00:30:24.070 26905-26905/com.example.testing.activityresulttest I/Activity_Test: NewActivity onStop
04-15 00:30:24.070 26905-26905/com.example.testing.activityresulttest I/Activity_Test: NewActivity onDestroy
可以看到,onActivityResult()在NewActivity创建之前被调用了,而且有意思的是生命周期onPause()>onActivityResult()>onResume()>onPause(),这个待分析,高手可以指点下。
这里可以引出第二个问题:也就是文章开头提到的面试题,onActivityResult()在被启动Activity退出前就被调用了。
答:这个可能跟将要启动的Activity的启动模式有关系。
另有时候,可能会需要知道第三个问题,onActivityResult()是在什么时候被调用的,而setResult()应该在什么时候调用?
答:很明显,onActivityResult()正常情况下在onRestart()之前被调用;而通常情况下,我们通过startActivityForResult()启动一个activity后,会进行一些处理得到我们要返回的数据时调用,并且随之我们调用finish()退出Activity返回启动它的Activity。
未完待续。。。