Android 组件系列-----Activity的传值和回传值
在这篇随笔里将讲解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>
我们来看看效果图: