Android关于startActivityForResult的基础知识分析
Android关于startActivityForResult的基础知识分析
1.startActivityForResult的使用场景是什么,onActivityResult回调里面的resultCode和requestCode的含义是什么?2.Activity A启动B的时候,在B中何时该执行setResult?setResult可以位于Activity的finish方法之后么?
问题1:
startActivityForResult的使用场景:
如果想在ActivityA中得到新打开ActivityB关闭后返回的数据,就需要使用startActivityForResulr(Intent intent,int requestCode)方法打开新的Activity,新的Activity关闭后会向前面的Activity传回数据,在前面的Activity重写onActivity(int requestCode,int resultCode,Intent data)方法即可得到数据。具体是:选择照片。选择联系人,进行数据编辑工作等等。
具体使用如下:
1.首先在之前界面调用startActivityForResult();来跳转界面
public class MainActivity extends Activity { private final static String TAG="MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button)findViewById(R.id.button_click); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //其中第二个参数是根据业务自行定义 startActivityForResult(new Intent(MainActivity.this,OtherActivity.class),5); } }); } //为了得到新界面回传的数据,必须重写重写onActivityResult方法 /** * requestCode 请求码 调用startActivityForResult()传递的值 * resultcode 结果码 用于标识是哪个Activity返回的 * * */ @Override protected void onActivityResult(int requestCode,int resultCode,Intent data){ String result = data.getExtras().getString("result_back");//得到新Activity 关闭后返回的数据 Log.i(TAG, result); } }当所要跳转的Activity关闭后,所要跳转的Activity返回的数据通过Intent进行传递,然后android会调用前面Activity的onActivityResult()方法把存放返回数据的intent作为第三个参数传入。在onActivityResult()方法使用第三个输入参数可以取出新Activity返回的数据
2.在所要跳转的Activity,关闭之前向前面的activity返回数据需要使用系统提供的setResult(int resultCode,Intent data)方法实现
public class OtherActivity extends Activity { private Button btn_setresult; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_other); btn_setresult = (Button)findViewById(R.id.btn_setresult); btn_setresult.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); //把返回数据存入Intent intent.putExtra("result_back", "My name is luguian"); //设置返回的数据 OtherActivity.this.setResult(5,intent); //关闭页面返回 OtherActivity.this.finish(); } }); } }
结果如下:
可以看出数据会传到原来的界面。
requestCode的含义:这个主要解决【区分多个异步任务】的问题,与其他异步API的设计类似,如果没有这个信息,那么Activity在收到响应时会进入混乱状态,比如不知道自己得到的是选择图片还是选择地址等等的结果。请求码的值是根据自己的业务来定义,请求码必须大于=0 因为只有非负数时新的ActivityRecoed对象的resultTo变量才指向发起者ActivityRecord对象。总而言之:就是区分标识请求来源。
具体使用例子:
@Override public void onCreate(Bundle savedInstanceState) { .... text1.setOnClickListener(new View.OnClickListener(){ public void onClick(View v) { startActivityForResult (new Intent(MainActivity.this, NewActivity.class), 5); } }); text2.setOnClickListener(new View.OnClickListener(){ public void onClick(View v) { startActivityForResult (new Intent(MainActivity.this, NewActivity.class),6); } }); @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch(requestCode){ case 5: //来自文本1的请求,作相应业务处理 case 6: //来自文本2的请求,作相应业务处理 } } }
resultCode的含义
异步调用结果码,告诉调用者成功/失败/其他信息 -- 该信息由被调用Activity/framework写入,经过AMS传递给源码。也可以根据resultCode来知道是哪个activity返回。具体使用如下:
public class OtheroneActivity extends Activity { ..... OtheroneActivity.this.setResult(1, intent); OtheroneActivity.this.finish(); } public class OthertwoActivity extends Activity { ...... OthertwoActivity.this.setResult(2, intent); OthertwoActivity.this.finish(); } public class MainActivity extends Activity { // 在该Activity会打开OtheroneActivity和OthertwoActivity @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch(resultCode){ case 1: // OtherOneActivity的返回数据 case 2: // OthertwoActivity的返回数据 } } }
2.Activity A启动B的时候,在B中何时该执行setResult?setResult可以位于Activity的finish方法之后么?
在onCreate.onStart,onResume调用setResult,都能在上一个Activity中回调onActivityResult,获取结果。
但是如果在onPause,onstop,onDestroy中调用setResult,回调onActivityResult的resultCode为RESULT_CANCELED(0),并且附带的resultData == null,原因是调用finish的时候会将resultCode和resultData通过ActivityManagerService传递出去,因此回调onPause,onStop,onDestroy的时候再执行setResult就没有什么作用了。
源码分析:
finish:
private void finish(int finishTask) { if (mParent == null) { int resultCode; Intent resultData; synchronized (this) { resultCode = mResultCode; resultData = mResultData; } if (false) Log.v(TAG, "Finishing self: token=" + mToken); try { if (resultData != null) { resultData.prepareToLeaveProcess(this); } if (ActivityManager.getService() .finishActivity(mToken, resultCode, resultData, finishTask)) { mFinished = true; } } catch (RemoteException e) { // Empty } } else { mParent.finishFromChild(this); } }
setResult:
public final void setResult(int resultCode, Intent data) { synchronized (this) { mResultCode = resultCode; mResultData = data; } }
也就是说finish后,resultcode置为0,resultData置为null,所以setResult不可以位于Activity的finish方法之后调用,会没有结果,无法将结果返回。
推荐阅读
-
Fedora14下android开发: eclipse与ibus确有冲突的问题分析
-
Android学习之Intent中显示意图和隐式意图的用法实例分析
-
Android Studio 3.0上分析内存泄漏的原因
-
Android编程自定义Dialog的方法分析
-
Android实现类似IOS右滑返回的效果(原因分析及解决办法)
-
SQL语句练习实例之五 WMS系统中的关于LIFO或FIFO的问题分析
-
Android颜色编辑器的制作中遇到的问题分析
-
深入解读php中关于抽象(abstract)类和抽象方法的问题分析
-
android startActivityForResult的使用方法介绍
-
基于android startActivityForResult的学习心得总结