Activity的startActivityForResult

鋸齒流沙發表於2017-12-26

作為Android開發人員,眾所周知,啟動Activity有兩個方法,一個是startActivity,另一個則是startActivityForResult。

startActivity(Intent intent):直接啟動Activity,只需要傳一個Intent型別的引數即可。

startActivityForResult(Intent intent, int requestCode):需要兩個引數,Intent和Int型別引數,使用該方法啟動Activity,當返回該Activity時,系統會自動呼叫Activity的onActivityResult方法進行回撥,那麼startActivityForResult有什麼作用呢?

startActivityForResult的作用(使用場景):Activity A需要在B中執行一些資料操作,而B又將執行結果返回給A。當我們關閉Activity B的時候,系統會自動呼叫A的onActivityResult方法。

    @Override
    protected void onActivityResult(
            int requestCode, 
            int resultCode, 
            Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

    }
複製程式碼

該方法有三個引數requestCode,resultCode和data:

data:Activity B關閉時候,通過呼叫setResult 方法,傳送給A的Intent資料。

resultCode:當前Activity返回原來Activity’的返回碼,通常為RESULT_CANCELED或RESULT_OK,也可以自己設定,通過返回碼可以判斷當前返回的資料是來源於那個Activity,然後做相應的業務處理。

requestCode:請求碼,根據業務需要自己設定,用於標識請求來源,如有三個Activity A、B、C, A和B都呼叫startActivityForResult啟動C,當C關閉後,系統都會呼叫A和B的onActivityResult方法,這時就可以使用請求碼來判斷是那個Activity開啟C的,然後做相應的業務處理。

從上面的分析中,我們注意到在Activity B關閉的時候需要呼叫setResult 方法才能夠將data和resultCode返回到A中的onActivityResult方法。那麼我們在B中何時執行該方法呢?執行該方法有何要求呢?

我們先看下Activity的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 方法必須要在執行finish方法之前執行,否則無效,也就是resultCode會返回預設值RESULT_CANCELED,而resultData會返回null。因為返回resultCode和resultData是在finishActivity的時候,所以setResult不可以位於Activity的finish方法之後。

下面我們實踐一個例子: MainActivity


public class MainActivity extends AppCompatActivity {

    private static final int A_REQUEST = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.findViewById(R.id.button01).setOnClickListener(mOnClickListener);

    }
    private View.OnClickListener mOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.button01:
                    Intent intent = new Intent(MainActivity.this,ResultActivity.class);
                    startActivityForResult(intent,A_REQUEST);
                    break;
                default:
                    break;

            }
        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        String a = data.getStringExtra("a");
        if (requestCode == A_REQUEST && resultCode == 1){
            Log.i("test",a);
        }

    }
}

複製程式碼

使用startActivityForResult方法啟動,並且傳入一個請求碼,在onActivityResult回撥方法中使用返回碼和請求碼進行判斷,然後獲取返回的資料,並列印出來。

ResultActivity:

public class ResultActivity extends AppCompatActivity {
    private static final int RESULT = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_result);
        Intent mIntent = new Intent();
        mIntent.putExtra("a","我是ResultActivity");
        // 設定結果,並進行傳送
        this.setResult(RESULT, mIntent);
        finish();
    }
}
複製程式碼

RESULT:返回碼 mIntent:返回的資料。

activity

上圖顯示,在MainActivity中,確實已經拿到了返回的資料,並列印出來。

相關文章