2009年6月2日 星期二

startActivity跟startActivityForResult

Android想切換新的Activity的時候
最常用的兩個函式就是startActivity跟startActivityForResult
比方說我想讓程式去開一個網頁就可以用

Uri uri=Uri.parse("http://www.google.com.tw");
Intent i=new Intent(Intent.ACTION_VIEW,uri);
startActivity(i);

在Android這個動作必須先創造Intent(意圖),也就是我有個"意圖"想要喚醒某個動作
但是我不能直接去叫用Activity,必須將想叫起的Activity變成Intent然後把意圖丟給startActivity,讓他去告訴Android我有個意圖,請他幫我執行,並且可以透過finish()關掉一個Activity

而startActivity跟startActivityForResult又有什麼不同?
startActivity是個單向開啟的動作,可以透過Bundle傳資料給下一個Activity
但是沒辦法從下一個Activity那邊接收訊息

舉個例子,有隻BMI的Activity想要把Data傳給Report這個Activity顯示


BMI.java

....
public void onClick(View v) {
Intent intent=new Intent();
intent.setClass(BMI.this, Report.class);
Bundle bundle=new Bundle();
bundle.putString("meta", "BMI:");
bundle.putDouble("BMI", 25.0);
intent.putExtras(bundle);
startActivity(intent);

}
...


Report.java

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.report);
TextView _msg=(TextView)findViewById(R.id.result);
Bundle b=this.getIntent().getExtras();
_msg.setText(b.getString("meta")+b.getDouble("BMI"));

透過意圖(Intent)把一些資訊一起帶給下一個Activity,並且新的Activity可以透過Intent收到資料

但是上面只能單向傳遞資料,可是有時候我希望可以從新的Activity得到一些資訊
這時候就能使用startActivityForResult,他代表我開啟一個Activity並等待他傳些東西回來,而使用startActivityForResult的時候,必須複寫Activity的onActivityResult函式才能真的有作用

舉個例子,假設我有個A想要開啟B並等待他傳回些什麼

A code

private static final int EDIT=1;
....
Intent intent=new Intent();
intent.setClass(this,Edit.class);
startActivityForResult(intent, EDIT);

startActivityForResult除了要傳輸的意圖之外,還要帶一個參數requestCode,這是為了讓接收資料的onActivityResult能夠辨別是哪個Activity回傳的資料,因為我可能一個Activity能夠開啟很多不同的Activity


B code

....
Intent i=new Intent();
Bundle b=new Bundle();
b.putString("B", "I am B");
i.putExtras(b);
setResult(RESULT_OK,i);
finish();
....

或者我不需要傳資料,只是通知A是B返回的

....
setResult(RESULT_OK);
finish();
....

setResult這個函式可以帶兩個參數,一個是resultCode,告知onActivityResult這次洞做是否成功,RESULT_OK是個常數,第二個參數是可選的,一個intent,主要是把資料回傳給上一個Activity,也可以不用回傳資料

最後回來看onActivityResult

A code

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

switch(requestCode){
case EDIT:

Toast.makeText(this, data.getExtras().getString("B"), 0).show();
}
}

onActivityResult帶三個參數
  1. requestCode:是對應上面的startActivityForResult的第二個參數,判斷是由哪個Activity回傳資料,上面我是用EDIT
    startActivityForResult(intent, EDIT);
    所以這邊用swtich去判斷他是不是EDIT,是的話就用Toast.makeText去製造一個訊息Bar把他顯示出來
  2. resultCode:對應B code的setResult()的第一個參數,其值是上面設的RESULT_OK,在此我們還用不到
  3. data:對應B code的setResult()的第二個參數(如果有設的話),有就是B回傳的資料,可以用data.getExtras()得到Bundle把資料取出來

沒有留言: