zoukankan      html  css  js  c++  java
  • 浅谈Android中的startActivityForResult和setResult方法

    引言

      我们知道,如果想打开一个新的Activity我们可以使用startActivity方法。今天我们介绍的startActivityForResult不仅可以打开全新的Activity,而且当新的Activity关闭后,父Activity可以接收到新窗口设置的值。这篇文章我们就来介绍下startActivityForResult和setResult这两个方法。下面来看例子吧。

    实例

      startActivityForResult方法

      我们来看一个简单的例子。这个例子的MainActivity上有两个按钮,点击这两个按钮都会打开一个全新的界面SecodeActivity,SecodeActivity在退出时会向MainActivity传递数据。我们首先来看下MainActivity的代码:

    package com.example.dreamgong.apprunresearch;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
    
        private Button mButton1;
        private Button mButton2;
    
        private static final int REQUESTCODE1=0x0001;
        private static final int REQUESTCODE2=0x0002;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initControl();
        }
    
    
        private void initControl() {
            mButton1=(Button)findViewById(R.id.button);
            mButton1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(getApplicationContext(),SecondActivity.class);
                    intent.putExtra("KEY1", "BTN1MSG1");
                    //打开新的Activity并且接受Activity的返回值
                    startActivityForResult(intent, REQUESTCODE1);
                }
            });
    
    
            mButton2=(Button)findViewById(R.id.button2);
            mButton2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(getApplicationContext(),SecondActivity.class);
                    intent.putExtra("KEY1", "BTN2MSG2");
                    //打开新的Activity并且接受Activity的返回值
                    startActivityForResult(intent, REQUESTCODE2);
                }
            });
        }
    
    
        /**
         * 当新打开的界面退出,处理返回的数据
         * @param requestCode
         * @param resultCode
         * @param data
         */
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if(resultCode==Activity.RESULT_OK) {
                if(requestCode==REQUESTCODE1){
                    String msg=data.getStringExtra("Second");
                    msg+="这是第一个按钮点击跳转的";
                    Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
                }
                if(requestCode==REQUESTCODE2){
                    String msg=data.getStringExtra("Second");
                    msg+="这是第二个按钮点击跳转的";
                    Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
                }
            }
        }
    
    
    }

      在代码中我们看到initControl方法主要负责初始化控件以及设置点击事件。我们看到两个按钮都设置了事件处理函数,都是跳转到SecondActivity。只是传递给SecondActivity界面的值不一致。我们也看到startActivityForResult方法的第二个参数是int类型的,需要传递RequestCode。

      RequestCode的作用:

      RequestCode的值是根据业务需要由自已设定,用于标识请求来源。例如:一个Activity有两个按钮,点击这两个按钮都会打开同一个Activity,不管是那个按钮打开新Activity,当这个新Activity关闭后,系统都会调用前面Activity的onActivityResult(int requestCode, int resultCode, Intent data)方法。在onActivityResult()方法如果需要知道新Activity是由那个按钮打开的。我们看到在onActivityResult方法中我们就是通过RequestCode来区分是哪一个按钮打开了新的界面,我们可以编写相应的业务代码。

      setResult方法

      下面我们来看SecondActivity中的逻辑代码,我们知道SecondActivity方法在关闭时需要向MainActivity方法中传递数据。怎么传递呢?我们结合Activity的生命周期来探究。

      我们先来看SecondActivity退出,MainActivity重新呈现时,这一流程方法的调用过程。B代表新打开的SecondActivity,A表示MainActivity。整个过程如下:

      B---onPause
      A---onActivityResult
      A---onRestart
      A---onStart
      A---onResume
      B---onStop
      B---onDestroy

      从上面过程可以看出,首先是B处于Pause 状态,然后等待A执行 onRestart——> onStart ——〉onResume,然后才是B 的onStop——>onDestroy,而A的 onActivityResult() 需要在B的onPause之后,A的onRestart之前这中间调用,所以B中的setResult()函数应该放在B的onPause之前调用。

      另外我试验了一下,如果把setResult()放在 B 的 onPause() 里面调用,结果仍然是无效的。

      那么setResult()应该在什么时候调用呢?从源码可以看出,Activity返回result是在被finish的时候,也就是说调用setResult()方法必须在finish()之前。所以在onPause、onStop、onDestroy方法中调用setResult()也有可能不会返回成功,因为这些方法调用不一定是在finish之前的。我们来详细看下源码:

      setResult()方法的源码:

    1 public final void setResult(int resultCode, Intent data) {
    2         synchronized (this) {
    3             mResultCode = resultCode;
    4             mResultData = data;
    5         }
    6 }

      finish()方法的源码:

     1 private void finish(boolean finishTask) {
     2         if (mParent == null) {
     3             int resultCode;
     4             Intent resultData;
     5             synchronized (this) {
     6                 resultCode = mResultCode;
     7                 resultData = mResultData;
     8             }
     9             if (false) Log.v(TAG, "Finishing self: token=" + mToken);
    10             try {
    11                 if (resultData != null) {
    12                     resultData.prepareToLeaveProcess();
    13                 }
    14                 if (ActivityManagerNative.getDefault()
    15                         .finishActivity(mToken, resultCode, resultData, finishTask)) {
    16                     mFinished = true;
    17                 }
    18             } catch (RemoteException e) {
    19                 // Empty
    20             }
    21         } else {
    22             mParent.finishFromChild(this);
    23         }
    24     }

      看代码的6,7行mResultCode是必须先经过setResult方法进行赋值的。所以setResult方法必须在finish方法之前调用!!!

      实际应用场景

      在实际使用中我们使用setResult方法一般都借助onBackPressed()方法或者点击事件。看下面的例子:

      1、按Back键(回退键):

      按BACK键从一个Activity退出来的,一按BACK,android就会自动调用Activity的finish()方法,方法:重写onBackPressed()方法,捕获BACK事件,捕获到之后先setResult。代码如下:

     1 @Override
     2     public void onBackPressed() {
     3 
     4         Intent intent=new Intent();
     5         intent.putExtra("Second","HELLO WORLD!!!");
     6         setResult(Activity.RESULT_OK,intent);
     7         finish();
     8         super.onBackPressed();
     9 
    10     }

      2、按点击事件中显式的调用finish()

      这时候整个执行流程如下:

      B---onBackPressed
      B---finish
      B---onPause
      A---onActivityResult
      A---onRestart
      A---onStart
      A---onResume
      B---onStop
      B---onDestroy

  • 相关阅读:
    nginx 服务企业应用
    3D模型展示以及体积、表面积计算
    php实现MySQL读写分离
    three.js实现3D模型展示
    thinkphp5.1+think-queue
    GIT记住远端仓库地址密码
    php实现采集(仅做参考)
    phpStudy集成环境apche+openssl配置本地https
    HTTP与HTTPS区别
    在父页面用Iframe加载子页面时,将父页面的title替换成子页面title
  • 原文地址:https://www.cnblogs.com/dreamGong/p/5200402.html
Copyright © 2011-2022 走看看