安卓漫漫路之startActivityForResult的使用.

在項目的界面跳轉時需要用到數據回傳.

可以使用google給咱們提供原生API---startActivityForResult(Intent intent, int requestCode)


三個主要的方法:
第一個:在界面A中使用:
startActivityForResult(Intent intent,int requestCode)打開界面B;
第二個:在界面B中使用:
setResult(int requestCode,Intent data)設置好數據後,
在手動調用finish關閉界面B是會向界面A回傳數據.
第三個:在界面A中通過重寫:
onActivityResult(int requestCode,int resultCode,,Intent data)
方法得到回傳的數據.


具體使用:

1.在界面A中的某點擊方法通過如下API開啓界面B:
startActivityForResult(new Intent(ActivityA.this,ActivityB.class),1);
PS:參數一爲intent,參數二爲請求碼(可根據需求編寫,用於標識請求來源);
2.在界面B中的返回鍵或者某返回Button的點擊事件中,通過如下API完成參數的回傳:
Intent intent = new Intent();
intent.putExtra("result","My name is Yang");
ActivityB.this.setResult(1,intent);
ActivityB.this.finish();
PS:如此即完成了界面B中參數回傳的操作.
3.在界面A中重寫onActivityResult得到回傳的數據;
String result = data.getExtras().getString("result");
Toast.makeText(this, result+"", Toast.LENGTH_SHORT).show();
這三步即可完成咱們的參數回調需求;
-------------------------------------------------------------------------------------
源碼實現:
setResult的源碼:
int mResultCode = RESULT_CANCELED;
Intent mResultData = null;

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

PS:把咱們傳入的結果碼和攜帶數據的回傳intent,賦值給Activity中的全局變量保存.
然後手動調用無參finish結束新界面時:
/** @hide Task isn't finished when activity is finished */
public static final int DONT_FINISH_TASK_WITH_ACTIVITY = 0;

public void finish() {
    finish(DONT_FINISH_TASK_WITH_ACTIVITY);
}


再繼續跟蹤一下這個finish(int finishTask):
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 (ActivityManagerNative.getDefault()
                    .finishActivity(mToken, resultCode, resultData, finishTask)) {
                mFinished = true;
            }
        } catch (RemoteException e) {
            // Empty
        }
    } else {
        mParent.finishFromChild(this);
    }
}


PS:ActivitymParent,現在我們只需知道mParent在一般情況下均爲null即可。
也就是說肯定會執行進入第一個判斷的方法體.
finishActivity方法執行完畢並返回mFinished =true.
再跟進下全局變量mFinished的使用:
@return If the activity is finishing, returns true; else returns false. 
public boolean isFinishing() {
    return mFinished;
} 


PS:此方法不用多說吧。判斷界面是否結束。看一眼上方的那行註釋就明白了根據返回值判定界面是否銷燬。

也就是說:通過調用ActivityManagerNative.getDefault()方法會得到一個ActivityManagerProxy對象,這是ActivityManagerService(下文簡稱爲AMS)的代理對象。那麼AMS是什麼呢?這裏我們只需要知道它是一個系統服務,系統中四大組件的啓動、切換、銷燬等都是由它負責的。
所以在調用完上方的finishActivity方法後,把mFinished變量置爲了true,也就是說Activity就被銷燬了,那麼回傳參數的主要邏輯就在resultData.prepareToLeaveProcess()這行代碼中了.能力有限只知道他的意思是準備離開應用程序進程,進入ActivityManagerService進程(意味着bundle的數據要在進程間傳遞);
onActivityResult的源碼:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {}

PS: 子類需要重寫實現,參數一是請求碼,參數二是結果碼,參數三是帶有回傳數據的intent。
-------------------------------------------------------------------------------------
但是還有請求碼和結果碼:
請求碼: 即是標明請求來源,如果多個請求要跳往同一個界面,即可用此區分請求.
結果碼: 即是標明結果來源,如果多個結果要回傳同一個界面,即可用此區分結果.

看如下的Demo即可明白請求碼與結果碼的區別使用,示例圖如下:

就兩個界面:
ActivityA的代碼如下:
public class Activity_A extends AppCompatActivity implements View.OnClickListener {

    private Button buttonA;
    private Button buttonB;
    private TextView name;
    private TextView age;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        //完成控件的初始化 和  設置控件的點擊事件
        buttonA = (Button) findViewById(R.id.button_a);
        buttonB = (Button) findViewById(R.id.button_b);
        age = (TextView) findViewById(R.id.age);
        name = (TextView) findViewById(R.id.name);
        buttonA.setOnClickListener(this);
        buttonB.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        //ButtonA和ButtonB的請求碼,標明請求來源
        int ButtonA = 1;
        int ButtonB = 2;
        switch (view.getId()) {
            case R.id.button_a://設置姓名  //第一個方法
                startActivityForResult(new Intent(Activity_A.this, Activity_B.class), ButtonA);
                break;
            case R.id.button_b://設置年齡  //第一個方法
                startActivityForResult(new Intent(Activity_A.this, Activity_B.class), ButtonB);
                break;
        }
    }
	//第三個方法
    @Override//參數一:請求碼,參數二:結果碼,參數三,回傳參數的intent;
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {   //根據請求碼來區別
            case 1: //如果請求碼爲1,即標明請求動作爲設置姓名;
                if (resultCode == 6){  //如果返回碼等於6,咱們在界面中指定好了保存姓名的返回碼;
                    String Name = data.getStringExtra("name");//獲取到返回的字符串
                    name.setText("姓名 :"+Name);             //設置到控件上
                    Toast.makeText(this, "完成了姓名的參數回傳", Toast.LENGTH_SHORT).show();
                }
                break;
            case 2: //如果請求碼爲2,即標明請求動作爲設置年齡;
                if (resultCode == 8){  //如果返回碼等於8,咱們在界面中指定好了保存年齡的返回碼;
                    String Age = data.getStringExtra("age");//獲取到返回的字符串
                    age.setText("年齡 :"+Age);             //設置到控件上
                    Toast.makeText(this, "完成了年齡的參數回傳", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }
}



ActivityB的代碼如下:
public class Activity_B extends AppCompatActivity {

    private EditText age;
    private EditText name;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);
        age = (EditText) findViewById(R.id.age);
        name = (EditText) findViewById(R.id.name);
        Activity_B.this.findViewById(R.id.saveName).setOnClickListener(new View.OnClickListener() {//保存
            @Override
            public void onClick(View view) {
                int resultName = 6; //姓名的返回碼
                String Name = name.getText().toString().trim();  //獲取到輸入的姓名
                Intent intentName = new Intent();               //創建意圖intentName
                intentName.putExtra("name",Name);               //保存參數Name
                Activity_B.this.setResult(resultName,intentName);  //寫好返回碼Name  //第二個方法
                Activity_B.this.finish();
            }
        });
        Activity_B.this.findViewById(R.id.saveAge).setOnClickListener(new View.OnClickListener() {//保存年齡
           @Override
            public void onClick(View view) {
                int resultAge = 8;  //年齡的返回碼
                String Age = age.getText().toString().trim();    //獲取到輸入的年齡
                Intent intentAge = new Intent();                //創建意圖intentAge
                intentAge.putExtra("age",Age);                   //保存參數Age 
                Activity_B.this.setResult(resultAge,intentAge);   //寫好返回碼Age  //第二個方法
                Activity_B.this.finish();  
            }
        });
    }
}





如有問題請多指正,您的指正使我更正確的前行.
發佈了26 篇原創文章 · 獲贊 39 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章