一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情。
Bundle简介
bundle在Android开发中非常常见,它的作用主要时用于传递数据;它所保存的数据是以key-value(键值对)的形式存在的,也就是说bundle是保存数据的容器,内部使用了Arraymap去存储数据,也提供了很多get,put方法。
Bundle 使用
Activity、Service、BroadcastReceiver 通过Intent传递Bundle数据。由于Bundle在借助Intent传递的数据可以是boolean、byte、int、long、float、double、string等基本类型或它们对应的数组,也可以是对象或对象数组。当Bundle传递的是对象或对象数组时,都需要进行序列化,也就是实现Serializable 或Parcelable接口。
Bundle 通讯示例
MultiProcessActivityA和MultiProcessActivityB分别在不同的两个进程里,从ActivityA中启动ActivityB,并且在ActivityB中获取ActivityA中传来的数据。
<activity android:name=".advance.multiprocess.ui.MultiProcessActivityA"
android:process=":process_a"/>//指定进程
<activity android:name=".advance.multiprocess.ui.MultiProcessActivityB"
android:process=":process_b"/>//指定进程
class MultiProcessActivityA: Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 数据组装
val bundle = Bundle()
bundle.putString("bundle", "Bundle是IPC通讯方式的一种")
val intent = Intent(this, MultiProcessActivityB::class.java)
intent.putExtras(bundle)
startActivity(intent)
}
}
class MultiProcessActivityB: Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//获取Bundle的信息
val bundle = intent.extras
val info = bundle!!.getString("bundle")
}
}
Bundle 源码分析
源码地址:frameworks\base\core\java\android\os\Bundle.java
这是一个有final 修饰的类,无法被其他类继承,本身是继承于BaseBundle,同时Bundle 实现了 Cloneable和Parcelable接口,必定会重载一下方法。
public Object clone();
public int describeContents();
public void writeToParcel(Parcel parcel, int flag);
public void readFromParcel(Parcel parcel);
public static final Parcelable.Creator<Bundle> CREATOR = new Parcelable.Creator<Bundle>();
构造函数
//构造一个新的空 Bundle。
public Bundle() {
super();
mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
//构造一个新的空 Bundle,使用 ClassLoader 来实例化 Parcelable 和 Serializable 对象。 loader 是在 Bundle 内实例化对象时使用的显式 ClassLoader。
public Bundle(ClassLoader loader) {
super(loader);
mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
//构造一个新的、空的 Bundle,其大小可容纳给定数量的元素。 Bundle 将根据需要增长。 capacity指代Bundle的初始容量
public Bundle(int capacity) {
super(capacity);
mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
//构造一个 Bundle,其中包含来自给定 Bundle 的映射副本。只做原始 Bundle 的浅拷贝
public Bundle(Bundle b) {
super(b);
mFlags = b.mFlags;
}
//构造一个 Bundle,其中包含来自给定 PersistableBundle 的映射副本。只做 PersistableBundle 的浅拷贝
public Bundle(PersistableBundle b) {
super(b);
mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
put、get 方法
Bundle的本质是对数据进行存储,所以提供了相应的put和get的方法,对于其支持的数据类型,他提供了一系列相关的put、get方法,Bundle之所以能以键值对的方式存储数据,实质上是因为它的父类BaseBundle内部维护了一个ArrayMap。
以putByte为例分析:
- Bundle中的putByte方法调用的是父类中的putByte方法
@Override
public void putByte(@Nullable String key, byte value) {
super.putByte(key, value);
}
- BaseBundle中的putByte主要就是执行了 unparcel()之后便以key-value的形式存入了mMap
void putByte(@Nullable String key, byte value) {
unparcel();
mMap.put(key, value);
}
- mMap的类型就是ArrayMap
@UnsupportedAppUsage
ArrayMap<String, Object> mMap = null;
以getByte为例分析:
- Bundle中的getByte方法调用的是父类中的getByte方法
@Override
public byte getByte(String key) {
return super.getByte(key);
}
- BaseBundle中的getByte主要就是执行了 unparcel()之后便从mMap当中取对应的value值
byte getByte(String key) {
unparcel();
return getByte(key, (byte) 0);
}