建立、配置和使用Activity——使用Bundle在Activity之间交换数据
当一个Activity启动另一个Activity时,常常会有一些数据需要传过去——这就像Web应用从一个Servlet跳到另一个Serlvet时,Web应用习惯把需要交换的数据放入requestScope、sessionScope中。对于Activity而言,在Activity之间进行数据交换更简单;因为两个Activity之间本来就有一个“信使”:Intent,因此我们主要将需要交换的数据放入Intent即可。
Intent提供了多个重载的方法来“携带”额外的数据,如下所示:
- putExtras(Bundle data):向Intent中放入需要“携带”的数据包。
- Bundle getExtras():取出Intent所“携带”的数据信息。
- putExtra(String name,Xxx value):向Intent中按key-value对的形式存入数据。
- getXxxExtra(String name):从Intent中按key取出指定类型的数据。
上面方法中的Bundle就是一个简单的数据携带包,该Bundle对象包含了多个方法来存入数据。
- putXxx(Stirng key,Xxx data):向Bundle放入Int、Long等各种类型的数据。
- putSerializable(String key,Serializable data):向Bundle中放入一个可序列化的对象。
为了取出Bundle数据携带包里的数据,Bundle提供了如下方法。
- getXxx(String key):从Bundle取出Int、Long等各种类型的数据。
- getSerializableExtra(String key):从Bundle取出一个可序列化的对象。
从上面的介绍不难看出,Intent主要通过Bundle对象来携带数据,因此Intent提供了putExtras()和getExtras()两个方法。除此之外,Intent也提供了多个重载putExtra(String name,Xxx value)、getXxxExtra(String name),那么这些方法存、取得数据在哪里呢?其实Intent提供的putExtra(String name,Xxx name),getXxxExtra(String name)方法,只是一个便捷的方法,这些方法是直接存、取Intent所携带的Bundle中的数据。
下面通过一个示例应用来介绍两个Activity之间如何通过Bundle交换数据。
实例:用第二个Activity处理注册信息
下面的程序包含两个Activity,其中第一个Activity用于收集用户的输入信息,当用户单击该Activity的“注册”按钮时,应用进入第二个Activity,第二个Activity将会获取第一个Activity中的数据。
下面是第一个Activity的界面布局文件。
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="请输入您的注册信息" android:textSize="20sp" /> <TableRow > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="用户名:" android:textSize="16sp"/> <!-- 定义一个EditText,用于收集用户的账号 --> <EditText android:id="@+id/name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="请填写想注册的账号" android:selectAllOnFocus="true"/> </TableRow> <TableRow > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="密码:" android:textSize="16sp"/> <!-- 用于收集用户的密码 --> <EditText android:id="@+id/passwd" android:layout_width="fill_parent" android:layout_height="wrap_content" android:password="true" android:selectAllOnFocus="true"/> </TableRow> <TableRow > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="性别:" android:textSize="16sp"/> <!-- 定义一组单选框,用于收集用户注册的性别 --> <RadioGroup > <RadioButton android:id="@+id/male" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="男" android:textSize="16sp"/> <RadioButton android:id="@+id/female" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="女" android:textSize="16sp"/> </RadioGroup> </TableRow> <Button android:id="@+id/bn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="注册" android:textSize="16sp"/> </TableLayout>
这个Activity的程序将会从Bundle中取出前一个Activity传过来的数据,并将它们显示出来。该Activity的Java代码如下:
package com.example.studyactivity; import com.example.Modle.Person; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.RadioButton; public class BundleTest extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bundle_test); Button bn=(Button)findViewById(R.id.bn); bn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub EditText name=(EditText)findViewById(R.id.name); EditText passwd=(EditText)findViewById(R.id.passwd); RadioButton male=(RadioButton)findViewById(R.id.male); String gender=male.isChecked()?"男":"女"; Person p=new Person(name.getText().toString(),passwd.getText().toString(), gender); //创建一个Bundle对象 Bundle data=new Bundle(); data.putSerializable("person", p); //创建一个Intent Intent intent=new Intent(BundleTest.this,ResultActivity.class); intent.putExtras(data); //启动Intent对应的Activity 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.bundle_test, menu); return true; } }
上面的程序中粗体字代码根据用户输入创建了一个Person对象,Person类只是一个简单的DTO对象,该Person类实现了java.io.Serializable接口,因此Person对象是可序列化的。
Person类的代码如下:
package com.example.Modle; import java.io.Serializable; public class Person implements Serializable{ private static final long serialVersionUID=1l; private Integer id; private String name; private String pass; private String gender; public Person() { } /* * @param name * @param pass * @param gender */ public Person(String name,String pass,String gender) { this.name=name; this.pass=pass; this.gender=gender; } public Integer getId() { return this.id; } public void setId(Integer id) { this.id=id; } public String getName() { return this.name; } public void setName(String name) { this.name=name; } public String getPass() { return this.pass; } public void setPass(String pass) { this.pass=pass; } public String getGender() { return this.gender; } public void setGender(String gender) { this.gender=gender; } }
上面的程序创建了一个Bundle对象,并调用了putSerializable("person",p)将Person对象放入该Bundle中,然后再使用Intent来“携带”这个Bundle,这样即可将Person对象传入第二个Activity。
运行该程序,第一个Activity显示的界面如图4.12所示。
当用户单击图4.12的“注册”按钮时,程序将会启动ResultActivity,并将用户输入的数据传入该Activity。下面是ResultActivity的界面布局文件。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="18sp" /> <TextView android:id="@+id/password" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="18sp"/> <TextView android:id="@+id/gender" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="18sp"/> </LinearLayout>
这个Activity的程序将会从Bundle中取出前一个Activity传过来的数据,并将它们显示出来。该Activity的Java代码如下。
package com.example.studyactivity; import com.example.Modle.Person; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.Menu; import android.widget.TextView; public class ResultActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_result); TextView name=(TextView)findViewById(R.id.name); TextView passwd=(TextView)findViewById(R.id.password); TextView gender=(TextView)findViewById(R.id.gender); //获取启动该ResultActivity的Intent Intent intent=getIntent(); //直接通过Intent取出它所携带的Bundle数据包中的数据 Person p=(Person)intent.getSerializableExtra("person"); name.setText("您的用户名为:"+p.getName().toString()); passwd.setText("您的密码为:"+p.getPass().toString()); gender.setText("您的性别为:"+p.getGender().toString()); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.result, menu); return true; } }
上面的程序中粗体字代码用于获取前一个Activity所传过来的数据,至于该Activity获取数据之后如何处理它们,完全由开发者自己决定。本应用程序只是将获取的数据显示出来,
用于在图4.12所示界面中输入注册信息之后,单击“注册”按钮将会看到如图4.13所示的界面。