欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android关于startActivityForResult的基础知识分析

程序员文章站 2022-04-01 20:09:36
Android关于startActivityForResult的基础知识分析 1.startActivityForResult的使用场景是什么,onActivityResult回...

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();
            }
        });

    }

}


结果如下:

Android关于startActivityForResult的基础知识分析

可以看出数据会传到原来的界面。

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);
        }
    }

 

Android关于startActivityForResult的基础知识分析

setResult:

    public final void setResult(int resultCode, Intent data) {
        synchronized (this) {
            mResultCode = resultCode;
            mResultData = data;
        }
    }

也就是说finish后,resultcode置为0,resultData置为null,所以setResult不可以位于Activity的finish方法之后调用,会没有结果,无法将结果返回。