使用 Bundle 在 Activity 之间交换数据
使用 Bundle 在 Activity 之间交换数据
场景
当一个 Activity 启动另一个 Activity 时,常常会有一些数据需要传过去。因为两个 Activity 之间本来就有一个 Intent,因此我们主要将需要交换的数据放入 Intent 中即可。
简介
Intent 提供了多个重载的方法来“携带”额外的数据。
- putExtras(Bundle data):向 Intent 中放下需要“携带”的数据包。
- Bundle getExtras():取出 Intent 中所“携带”的数据包。
- putExtra(String key, Xxx value):向 Intent 中按 key-value 对的形式存入数据。
- getXxxExtra(String key):从 Intent 中按 key 取出指定类型的数据。
类型讲解
上面方法中的 Bundle 就是一个简单地数据携带包,该 Bundle 对象包含了多个方法来存入数据。
- putXxx(String key, Xxx value):向 Bundle 中放入 Int、Long 等各种类型的数据。
- putSerializable(String key, Serializable value):向 Bundle 中放入一个可序列化的对象。
- putParcelable(String key, Parcelable value):向 Bundle 中放入一个可序列化的对象。
bundle提取数据
为了取出 Bundle 数据携带包的数据,Bundle 提供了如下方法。
- getXxx(String key):从 Bundle 中取出 Int、Long 等各种类型的数据。
- getSerializable(String key):从 Bundel 中取出一个可序列化的对象。
- getParcelable(String key):从 Bundel 中取出一个可序列化的对象。
从上面的介绍不难看出,Intent 主要通过 Bundle 对象来携带数据,因此 Intent 提供了 putExtras()和 getExtras()两个方法。除此之外,Intent 也提供了多个重载的 putExtra(String key,Xxx value)、getXxxExtra(String key)。其实 Intent 提供的 putExtra(String key,Xxx value)、getXxxExtra(String key)方法,只是两个便捷的方法,这些方法依然是存取 Intent 所携带的 Bundle 中的数据。
提示点
值得注意的是:
Intent 的 putExtra(String key, XXxx value)方法是“智能”的,当程序调用 Intent 的 putExtra(String key,Xxx value)方法向 Intent 中存入数据时,如果该 Intent 中已经携带了 Bundle 对象,则该方法直接向 Intent 所携带的 Bundle 中存入数据;如果 Intent 还没有携带 Bundle 对象,putExtra(String key,Xxx value)方法会优先为 Intent 创建一个 Bundle,再向 Bundle 中存入数据。
实例:用第二个 Activity 处理注册信息
<?xml version="1.0" encoding="utf-8"?><TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="请输入您的注册信息"
android:textSize="20sp"/>
<TableRow>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="用户名:"
android:textSize="16sp"/>
<!-- 定义一个EditText,用于收集用户的账号 -->
<EditText
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请填写想注册的账号"
android:selectAllOnFocus="true"/>
</TableRow>
<TableRow>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="密码:"
android:textSize="16sp"/>
<!-- 用于收集用户的密码 -->
<EditText
android:id="@+id/passwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:password="true"
android:selectAllOnFocus="true"/>
</TableRow>
<TableRow>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="性别:"
android:textSize="16sp"/>
<!-- 定义一组单选框,用于收集用户注册的性别 -->
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<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>
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button bn = (Button) findViewById(R.id.bn);
bn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
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(MainActivity.this,
ResultActivity.class);
intent.putExtras(data);
// 启动intent对应的Activity
startActivity(intent);
}
});
}
}
下面是 ResultActivity 的界面布局文件。
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- 定义三个TextView,用于显示用户输入的数据 -->
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"/>
<TextView
android:id="@+id/passwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"/>
<TextView
android:id="@+id/gender"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"/>
</LinearLayout>
public class ResultActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.result);
TextView name = (TextView) findViewById(R.id.name);
TextView passwd = (TextView) findViewById(R.id.passwd);
TextView gender = (TextView) findViewById(R.id.gender);
// 获取启动该Activity的Intent
Intent intent = getIntent();
// 直接通过Intent取出它所携带的Bundle数据包中的数据
Person p = (Person) intent.getSerializableExtra("person");
name.setText("您的用户名为:" + p.getName());
passwd.setText("您的密码为:" + p.getPasswd());
gender.setText("您的性别为:" + p.getGender());
}
}
public class Person implements Serializable {
private Integer id;
private String name;
private String passwd;
private String gender;
public Person(String name, String passwd, String gender) {
this.name = name;
this.passwd = passwd;
this.gender = gender;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
启动其他 Activity 并返回结果
Activity 还提供了一个 startActivityForResult(Intent intent,int requestCode)方法来启动其他 Activity。该方法用于启动指定 Activity,而且期望获取指定 Activity 返回的结果。
为了获取被启动的 Activity 所返回的结果,需要从两个方面着手。
- 当前 Activity 需要重写 onActivityResult(int requestCode, int resultCode, Intent intent),当被启动的 Activity 返回结果时,该方法将会被触发,其中 requestCode 代表请求码,而 resultCode 代表 Activity 返回的结果码,这个结果码也是由开发者根据业务自行设定的。
- 被启动的 Activity 需要调用 setResult()方法设置处理结果。
实例:用第二个 Activity 让用户选择信息
public class MainActivity extends Activity {
Button bn;
EditText city;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取界面上的组件
bn = (Button) findViewById(R.id.bn);
city = (EditText) findViewById(R.id.city);
// 为按钮绑定事件监听器
bn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View source) {
// 创建需要对应于目标Activity的Intent
Intent intent = new Intent(MainActivity.this,
SelectCityActivity.class);
// 启动指定Activity并等待返回的结果,其中0是请求码,用于标识该请求
startActivityForResult(intent, 0);
}
});
}
// 重写该方法,该方法以回调的方式来获取指定Activity返回的结果
@Override
public void onActivityResult(int requestCode
, int resultCode, Intent intent) {
// 当requestCode、resultCode同时为0时,也就是处理特定的结果
if (requestCode == 0 && resultCode == 0) {
// 取出Intent里的Extras数据
Bundle data = intent.getExtras();
// 取出Bundle中的数据
String resultCity = data.getString("city");
// 修改city文本框的内容
city.setText(resultCity);
}
}
}
为了让当前 Activity 获取 SelectCityActivity 所返回的结果,开发者应该重写 onActivityResult()方法—-当被启动的 SelectCityActivity 返回结果时,onActivityResult()方法将会被调用。
因此还需要为上面 ActivityForResult 添加如下方法。
// 重写该方法,该方法以回调的方式来获取指定Activity返回的结果
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
// 当requestCode、resultCode同时为0时,也就是处理特定的结果
if (requestCode == 0 && resultCode == 0) {
// 取出Intent里的Extras数据
Bundle data = intent.getExtras();
// 取出Bundle中的数据
String resultCity = data.getString("city");
// 修改city文本框的内容
city.setText(resultCity);
}
}
public class SelectCityActivity extends ExpandableListActivity {
// 定义省份数组
private String[] provinces = new String[]
{"广东", "广西", "湖南"};
private String[][] cities = new String[][]
{
{"广州", "深圳", "珠海", "中山"},
{"桂林", "柳州", "南宁", "北海"},
{"长沙", "岳阳", "衡阳", "株洲"}
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ExpandableListAdapter adapter = new BaseExpandableListAdapter() {
// 获取指定组位置、指定子列表项处的子列表项数据
@Override
public Object getChild(int groupPosition, int childPosition) {
return cities[groupPosition][childPosition];
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public int getChildrenCount(int groupPosition) {
return cities[groupPosition].length;
}
private TextView getTextView() {
AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, 64);
TextView textView = new TextView(SelectCityActivity.this);
textView.setLayoutParams(lp);
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
textView.setPadding(36, 0, 0, 0);
textView.setTextSize(20);
return textView;
}
// 该方法决定每个子选项的外观
@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
TextView textView = getTextView();
textView.setText(getChild(groupPosition, childPosition)
.toString());
return textView;
}
// 获取指定组位置处的组数据
@Override
public Object getGroup(int groupPosition) {
return provinces[groupPosition];
}
@Override
public int getGroupCount() {
return provinces.length;
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
// 该方法决定每个组选项的外观
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
LinearLayout ll = new LinearLayout(SelectCityActivity.this);
ll.setOrientation(LinearLayout.HORIZONTAL);
ImageView logo = new ImageView(SelectCityActivity.this);
ll.addView(logo);
TextView textView = getTextView();
textView.setText(getGroup(groupPosition).toString());
ll.addView(textView);
return ll;
}
@Override
public boolean isChildSelectable(int groupPosition,
int childPosition) {
return true;
}
@Override
public boolean hasStableIds() {
return true;
}
};
// 设置该窗口显示列表
setListAdapter(adapter);
getExpandableListView().setOnChildClickListener(
new OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent,
View source, int groupPosition, int childPosition,
long id) {
// 获取启动该Activity之前的Activity对应的Intent
Intent intent = getIntent();
intent.putExtra("city",
cities[groupPosition][childPosition]);
// 设置该SelectCityActivity的结果码,并设置结束之后退回的Activity
SelectCityActivity.this.setResult(0, intent);
// 结束SelectCityActivity。
SelectCityActivity.this.finish();
return false;
}
});
}
}