一、 当一个Activity想对另一个Activity说悄悄话时...
想象一下:你正在用一款“相亲APP”刷帅哥美女,突然看到一个心动的头像,手指不由自主点下去——唰!跳转到详细资料页面,年龄身高兴趣爱好一字不排开。这背后,就是两个Activity在说悄悄话:“嘿,我把用户ID给你,你快去数据库查查这人啥来头!”
在没有Bundle的年代,Activity之间传数据就像让两个聋哑人比划手势,一个拼命比划“我要用户123的数据”,另一个一脸懵逼。最后只好动用全局变量这种“大喇叭广播”,结果全APP都听见了,隐私全无还容易串台。
Bundle的出现,简直是人类之光! 它就像个智能快递箱,把数据打包贴好标签,安全送到另一个Activity手里。隔壁iOS开发看了都直呼内行!
二、 Bundle是何方神圣?能塞哪些“私货”?
Bundle本质上是个键值对(Key-Value)容器,可以理解为Android特供版的“快递纸箱”。但别小看这个纸箱,它可是开过光的:
- 支持数据类型超全:八大基本类型(int、double等)和它们的数组、String、CharSequence、Parcelable对象... 甚至能塞进整个Serializable对象!
- 自动序列化打包:像用真空压缩袋装羽绒服,复杂数据瞬间压扁成二进制流
- 跨进程都能传:不光同一APP内,连不同APP之间都能用它传小纸条(当然要权限啦)
不过要注意:别什么破烂都往里塞!大数据对象(比如高清图片)直接传Bundle,会像让快递小哥扛冰箱上楼——分分钟累趴下。这时候就该请出全局缓存或者文件存储了。
三、 实战:打造一款“相亲APP”的数据传递
来吧,直接上手!我们要实现:主页面显示帅哥列表,点击任意 item,跳转到详情页并显示对应信息。
第1步:准备两个Activity的布局(XML文件)
activity_main.xml(主页 - 列表页面):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="优质单身帅哥推荐"
android:textSize="24sp"
android:gravity="center"/>
<ListView
android:id="@+id/lv_dating_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
activity_profile.xml(详情页):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="姓名"
android:textSize="20sp" />
<TextView
android:id="@+id/tv_age"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="年龄" />
<TextView
android:id="@+id/tv_hobby"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="兴趣爱好" />
</LinearLayout>
第2步:编写主页MainActivity - 负责打包数据
public class MainActivity extends AppCompatActivity {
private ListView mListView;
private String[] names = {"程序员小张", "设计师老王", "产品经理老李"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = findViewById(R.id.lv_dating_list);
// 创建简单适配器显示列表
ArrayAdapter<String> adapter = new ArrayAdapter<>(
this,
android.R.layout.simple_list_item_1,
names
);
mListView.setAdapter(adapter);
// 关键代码:列表点击事件
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// 创建Intent:明确要从MainActivity跳转到ProfileActivity
Intent intent = new Intent(MainActivity.this, ProfileActivity.class);
// 创建Bundle并塞数据
Bundle bundle = new Bundle();
bundle.putString("name", names[position]);
bundle.putInt("age", 25 + position); // 假装算年龄
bundle.putStringArray("hobbies", new String[]{
"写代码", "修电脑", "吐槽产品经理"
});
// 把Bundle绑在Intent上
intent.putExtras(bundle);
// 发货!
startActivity(intent);
}
});
}
}
第3步:编写详情页ProfileActivity - 负责拆包数据
public class ProfileActivity extends AppCompatActivity {
private TextView tvName, tvAge, tvHobby;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
// 初始化控件
tvName = findViewById(R.id.tv_name);
tvAge = findViewById(R.id.tv_age);
tvHobby = findViewById(R.id.tv_hobby);
// 关键代码:从Intent中取出Bundle
Intent intent = getIntent();
if (intent != null) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
// 拆包!记得设置默认值防止空指针
String name = bundle.getString("name", "未知");
int age = bundle.getInt("age", 0);
String[] hobbies = bundle.getStringArray("hobbies");
// 显示到UI
tvName.setText("姓名:" + name);
tvAge.setText("年龄:" + age);
if (hobbies != null) {
tvHobby.setText("爱好:" + String.join("、", hobbies));
}
}
}
}
}
第4步:别忘了在AndroidManifest.xml注册ProfileActivity!
<application>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 必须注册!否则系统找不到详情页 -->
<activity android:name=".ProfileActivity" />
</application>
运行效果:点击“程序员小张” -> 跳转详情页显示“姓名:程序员小张 年龄:25 爱好:写代码、修电脑、吐槽产品经理”。完美!
四、 那些年,我们踩过的Bundle坑
- 键名打错字:bundle.putString("name") 然后 getString("nama")——系统不会报错,只会返回null,然后你对着空页面怀疑人生
- 类型不匹配:存了Integer却想用getString取?恭喜获得ClassCastException豪华大礼包!
- 数据太大:试图传递2MB的Bitmap,直接触发TransactionTooLargeException。解决方案:用全局缓存或者图片路径
- 忘记判空:没检查bundle是否为null就直接get,APP分分钟崩溃给你看
防坑指南:建议定义常量类统一管理键名:
public class BundleKeys {
public static final String KEY_NAME = "name";
public static final String KEY_AGE = "age";
// ...其他键名
}
使用时:bundle.putString(BundleKeys.KEY_NAME, "小王"),从根源杜绝拼写错误!
五、 进阶玩法:Bundle的隐藏技能
- 选择性回传:用startActivityForResult启动页面,详情页关闭时还能回传数据给主页(比如用户修改了资料)
- Parcelable黑科技:自定义对象实现Parcelable接口,比Serializable快10倍!适合复杂对象传输
- 与Fragment暧昧:Bundle同样是Fragment间传值的神器,用法一模一样
六、 总结
Bundle就像Activity之间的“联邦快递”——简单、可靠、啥都能寄。掌握它,你就打通了Android页面通信的任督二脉。记住核心三步曲:打包(put)、绑定(intent)、拆包(get)。
下次再看到同事用全局变量在Activity间传数据,请直接把这篇教程拍他脸上:“兄弟,2024年了,该用Bundle了!”

被折叠的 条评论
为什么被折叠?



