Android 元件系列-----Activity的傳值和回傳值

xiaoluo501395377發表於2013-11-10

在這篇隨筆裡將講解Activity的傳值和回傳值。

一、通過startActivity來進行Activity的傳值

在Android中,如果我們要通過一個Activity來啟動另一個Activity,可以使用 startActivity(Intent intent)方法來傳入一個Intent物件,這個Intent物件我們可以精確的指定我們需要跳轉的Activity上,或者通過Intent物件來指定我們要完成的一個action操作。

①.通過setClass方法來指定我們要跳轉的Activity

Intent intent = new Intent();
intent.setClass(MainActivity.this, SecondActivity.class);

②.通過setAction方法來我們要完成的一個action操作

Intent  intent = new Intent();
intent.setAction("com.xiaoluo.android_intent.second");

通過這種方式可以來指定我們的Intent物件要完成某個操作,這個操作可以是啟動一個Activity,我們可以在AndroidManifest.xml中在 <Activity> 元素下指定一個 <intent-filter> 物件,然後其子元素宣告一個 <action> 元素,這樣我們可以將這個action動作繫結到了這個Activity上,即Android作業系統會去找與intent物件中指定的action名字的 <intent-filter>物件,然後執行相應的動作,例如:

     <activity 
            android:name="com.xiaoluo.android_intent.SecondActivity"
            android:label="SecondActivity">
            <intent-filter>
                <action android:name="com.xiaoluo.android_intent.second"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

這樣我們的Intent物件,在啟動時,就會找到名字為 com.xiaoluo.android_intent.second 的<intent-filter>物件,來啟動我們的SecondActivity。

我們來看看如何在Activity物件中進行值的傳遞,也是通過 Intent 物件的各種putExtra方法來進行傳遞:

MainActivity:

public class MainActivity extends Activity
{
    private Button button;
    
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new ButtonListener());
    }

    class ButtonListener implements OnClickListener
    {
        @Override
        public void onClick(View v)
        {
//            Intent intent = new Intent();
//            intent.setClass(MainActivity.this, SecondActivity.class);
            Intent  intent = new Intent();
            intent.setAction("com.xiaoluo.android_intent.second");
            
            intent.putExtra("com.xiaoluo.android_intent.age", 20); // 第一個引數指定name,android規範是以包名+變數名來命名,後面是各種型別的資料型別
            intent.putExtra("com.xiaoluo.android_intent.name", "xiaoluo");
            
            Bundle bundle = new Bundle();  //  Bundle的底層是一個HashMap<String, Object
            bundle.putString("hello", "world");
            intent.putExtra("bundle", bundle);
            
            startActivity(intent);
        }
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

SecondActivity:

public class SecondActivity extends Activity
{
    private TextView textView;
    private final String TAG = "SecondActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second);
        
        textView = (TextView)findViewById(R.id.textView);
        
        //    得到跳轉到該Activity的Intent物件
        Intent intent = getIntent();
        
        int age = intent.getIntExtra("com.xiaoluo.android_intent.age", 10);
        String name = intent.getStringExtra("com.xiaoluo.android_intent.name");
        Bundle bundle = intent.getBundleExtra("bundle");
        String world = bundle.getString("hello");
        
        Log.i(TAG, age + ", " + name + ", " + world);
         
        textView.setText(name + " : " + age + ", " + world);
        
        System.out.println(intent);
    }
}

在第二個Activity物件中,可以通過 getIntent() 方法來得到跳轉到這個Activity的Intent物件,然後通過 Intent 物件的各種 getXXExtra 方法來得到我們的傳過來的值。

AndroidManifest.xml檔案如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xiaoluo.android_intent"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.xiaoluo.android_intent.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <activity 
            android:name="com.xiaoluo.android_intent.SecondActivity"
            android:label="SecondActivity">
            <intent-filter>
                <action android:name="com.xiaoluo.android_intent.second"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

這樣我們就可以實現Activity直接的值的傳遞。

二、通過startActivityForResult方法來得到Activity的回傳值

在一些情況下,我們通過 A activity跳轉到 B activity上,這時希望 A activtiy能從 B activity上得到一些返回值,這個時候我們就不能使用startActivity方法了,而是使用 startActivityForResult方法來完成我們的操作。

例如,我們希望完成下面一個功能,在MainActivity上,寫上一個算術表示式,然後跳轉到到第二個SecondActivity上,在這個Activity上將第一個Activity的表示式顯示出來,然後我們可以輸入我們的算術表示式結果,然後點選按鈕,將這個結果值又返回給我們的MainActivity,並將結果填充到算術表示式中,具體看如下程式碼:

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <EditText
        android:id="@+id/editText1"
        android:layout_width="70dp"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="60dp"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/editText1"
        android:text=" + "
        android:textSize="30sp" />

    <EditText
        android:id="@+id/editText2"
        android:layout_width="60dp"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/textView1" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/editText2"
        android:text=" = "
        android:textSize="30sp" />

    <EditText
        android:id="@+id/editText3"
        android:layout_width="70dp"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/textView2" />
    
    <Button 
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/editText3"
        android:layout_centerInParent="true"
        android:layout_marginTop="30dp"
        android:text="跳轉到SecondActivity"/>

</RelativeLayout>

second.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
    <TextView
        android:id="@+id/textView1"
        android:layout_width="70dp"
        android:layout_height="wrap_content"
        android:textSize="20sp"/>
    
    <EditText 
        android:id="@+id/editText1"
        android:layout_width="60dp"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/textView1"/>
    
    <Button 
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/editText1"
        android:text="返回給MainActivity"/>
    
</RelativeLayout>

然後我們來看看兩個Activity

MainActivity:

public class MainActivity extends Activity
{
    private Button button;
    private EditText editText1;
    private EditText editText2;
    private EditText editText3;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        button = (Button)findViewById(R.id.button);
        editText1 = (EditText)findViewById(R.id.editText1);
        editText2 = (EditText)findViewById(R.id.editText2);
        editText3 = (EditText)findViewById(R.id.editText3);
        
        button.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                Intent intent = new Intent();
                intent.putExtra("message", editText1.getText().toString().trim() + " + " + editText2.getText().toString().trim() + " = ?");
                intent.setClass(MainActivity.this, SecondActivity.class);
                /*
                 * 如果希望啟動另一個Activity,並且希望有返回值,則需要使用startActivityForResult這個方法,
                 * 第一個引數是Intent物件,第二個引數是一個requestCode值,如果有多個按鈕都要啟動Activity,則requestCode標誌著每個按鈕所啟動的Activity
                 */
                startActivityForResult(intent, 1000);
            }
        });
    }
    
    /**
     * 所有的Activity物件的返回值都是由這個方法來接收
     * requestCode:    表示的是啟動一個Activity時傳過去的requestCode值
     * resultCode:表示的是啟動後的Activity回傳值時的resultCode值
     * data:表示的是啟動後的Activity回傳過來的Intent物件
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == 1000 && resultCode == 1001)
        {
            String result_value = data.getStringExtra("result");
            editText3.setText(result_value);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

我們看到,這裡我們使用的是 startActivityForResult 的這個方法,

public void startActivityForResult (Intent intent, int requestCode)

Same as calling startActivityForResult(Intent, int, Bundle) with no options.

Parameters
intent    The intent to start.
requestCode    If >= 0, this code will be returned in onActivityResult() when the activity exits.
Throws   android.content.ActivityNotFoundException

第一個指定我們的Intent物件,第二個requestCode指定我們的一個啟動標誌值,因為我們可能有多個按鈕,如果都是跳轉到同一個Activity物件上,我們需要對其進行標誌,才知道是哪個Activity物件跳轉過來的。

我們看到這裡還有一個 onActivityResult 方法,這個方法就是用來處理我們Activity的回傳值的方法,所有的Activity回傳值的操作都是在這個方法中完成。

protected void onActivityResult (int requestCode, int resultCode, Intent data)

Called when an activity you launched exits, giving you the requestCode you started it with, the resultCode it returned, and any additional data from it. The resultCode will be RESULT_CANCELED if the activity explicitly returned that, didn't return any result, or crashed during its operation.

You will receive this call immediately before onResume() when your activity is re-starting.

Parameters
requestCode    The integer request code originally supplied to startActivityForResult(), allowing you to identify who this result came from.
resultCode    The integer result code returned by the child activity through its setResult().
data    An Intent, which can return result data to the caller (various data can be attached to Intent "extras").

接下來,我們看看SecondActivity這個類:

public class SecondActivity extends Activity
{
    private Button button;
    private TextView textView;
    private EditText editText;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second);
        
        button = (Button)findViewById(R.id.button1);
        textView = (TextView)findViewById(R.id.textView1);
        editText = (EditText)findViewById(R.id.editText1);
        
        Intent intent = getIntent();
        String message = intent.getStringExtra("message").toString().trim();
        textView.setText(message);
        
        button.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                String result = editText.getText().toString().trim();
                Intent intent = new Intent();
                intent.putExtra("result", result);
                /*
                 * 呼叫setResult方法表示我將Intent物件返回給之前的那個Activity,這樣就可以在onActivityResult方法中得到Intent物件,
                 */
                setResult(1001, intent);
                //    結束當前這個Activity物件的生命
                finish();
            }
        });
    }
}

這個類裡面我們將MainActivity傳過來的值給TextView賦上,然後通過點選按鈕將值回傳給我們的 MainActivity,通過 setResult 方法可以將我們的值儲存在Intent物件中,並返回給MainActivity物件,通過的 onActivityResult 方法來處理得到的回傳Intent物件。finish()方法我們可以顯示的結束這個Activity物件的生命。

最後我們來看一下AndroidManifest.xml檔案:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xiaoluo.android_activity"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.xiaoluo.android_activity.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.xiaoluo.android_activity.SecondActivity"
            android:label="SecondActivity" >
        </activity></application>

</manifest>

我們來看看效果圖:

 

 

相關文章