android bundle机制6,详解 Android IPC 机制(三)使用 Bundle 实现进程间通信

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

在 Android 四大组件中 Activity、Service、Receiver 都支持在 Intent 中附加传递 Bundle 数据。

Bundle 是以键值对的形式存储数据,支持基本数据类型、数组、实现 Serializable 或 Parcelable 接口的对象以及一些 Android 支持的特殊对象。// 发送数据

Intent intent = new Intent(MainActivity.this, SecondActivity.class);

Bundle bundle = new Bundle();

bundle.putString("userName", "wshunli");

intent.putExtras(bundle);

startActivity(intent);

// 接收数据

Bundle bundle = getIntent().getExtras();

String userName = null;

if (bundle != null) {

userName = bundle.getString("userName");

}

Log.d(TAG, "userName: " + userName);

使用 Bundle 的 put 与 get 方法族将数据保存至 bundle 对象,调用 Intent 的 putExtras 方法即可。

Bundle 源码分析,Bundle 继承自 BaseBundle 并实现了 Cloneable 和 Parcelable 接口。

以 Boolean 类型数据存取为例:ArrayMap mMap = null;

public void putBoolean(@Nullable String key, boolean value) {

unparcel();

mMap.put(key, value);

}

public boolean getBoolean(String key, boolean defaultValue) {

unparcel();

Object o = mMap.get(key);

if (o == null) {

return defaultValue;

}

try {

return (Boolean) o;

} catch (ClassCastException e) {

typeWarning(key, o, "Boolean", defaultValue, e);

return defaultValue;

}

}

根据源码可知数据存取都是在 ArrayMap 对象中。

其中 unparcel() 方法源码如下:/*

* If mParcelledData is non-null, then mMap will be null and the

* data are stored as a Parcel containing a Bundle. When the data

* are unparcelled, mParcelledData willbe set to null.

*/

Parcel mParcelledData = null;

/* package */ void unparcel() {

synchronized (this) {

final Parcel source = mParcelledData;

if (source != null) {

initializeFromParcelLocked(source, /*recycleParcel=*/ true);

} else {

if (DEBUG) {

Log.d(TAG, "unparcel "

+ Integer.toHexString(System.identityHashCode(this))

+ ": no parcelled data");

}

}

}

}

private void initializeFromParcelLocked(@NonNull Parcel parcelledData, boolean recycleParcel) {

if (LOG_DEFUSABLE && sShouldDefuse && (mFlags & FLAG_DEFUSABLE) == 0) {

Slog.wtf(TAG, "Attempting to unparcel a Bundle while in transit; this may "

+ "clobber all data inside!", new Throwable());

}

if (isEmptyParcel(parcelledData)) {

if (DEBUG) {

Log.d(TAG, "unparcel "

+ Integer.toHexString(System.identityHashCode(this)) + ": empty");

}

if (mMap == null) {

mMap = new ArrayMap<>(1);

} else {

mMap.erase();

}

mParcelledData = null;

return;

}

final int count = parcelledData.readInt();

if (DEBUG) {

Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))

+ ": reading " + count + " maps");

}

if (count < 0) {

return;

}

ArrayMap map = mMap;

if (map == null) {

map = new ArrayMap<>(count);

} else {

map.erase();

map.ensureCapacity(count);

}

try {

parcelledData.readArrayMapInternal(map, count, mClassLoader);

} catch (BadParcelableException e) {

if (sShouldDefuse) {

Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);

map.erase();

} else {

throw e;

}

} finally {

mMap = map;

if (recycleParcel) {

recycleParcel(parcelledData);

}

mParcelledData = null;

}

if (DEBUG) {

Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))

+ " final map: " + mMap);

}

}

只有使用 Bundle 构造函数实例化 Bundle 对象时,才会给 mParcelledData 赋值,其他大部分情况下 mParcelledData 都是 null 。BaseBundle(Parcel parcelledData) {

readFromParcelInner(parcelledData);

}

void readFromParcelInner(Parcel parcel) {

// Keep implementation in sync with readFromParcel() in

// frameworks/native/libs/binder/PersistableBundle.cpp.

int length = parcel.readInt();

readFromParcelInner(parcel, length);

}

private void readFromParcelInner(Parcel parcel, int length) {

if (length < 0) {

throw new RuntimeException("Bad length in parcel: " + length);

} else if (length == 0) {

// Empty Bundle or end of data.

mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL;

return;

}

final int magic = parcel.readInt();

if (magic != BUNDLE_MAGIC) {

throw new IllegalStateException("Bad magic number for Bundle: 0x"

+ Integer.toHexString(magic));

}

if (parcel.hasReadWriteHelper()) {

// If the parcel has a read-write helper, then we can't lazily-unparcel it, so just

// unparcel right away.

synchronized (this) {

initializeFromParcelLocked(parcel, /*recycleParcel=*/ false);

}

return;

}

// Advance within this Parcel

int offset = parcel.dataPosition();

parcel.setDataPosition(MathUtils.addOrThrow(offset, length));

Parcel p = Parcel.obtain();

p.setDataPosition(0);

p.appendFrom(parcel, offset, length);

p.adoptClassCookies(parcel);

if (DEBUG) Log.d(TAG, "Retrieving " + Integer.toHexString(System.identityHashCode(this))

+ ": " + length + " bundle bytes starting at " + offset);

p.setDataPosition(0);

mParcelledData = p;

}

从上述代码片段可以知道 mParcelledData 的取值有3种情况:mParcelledData = null

mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL

mParcelledData = Parcel.obtain()

在 unparcel() 方法中分别对这三种情况进行了处理,如果为 null 不进行任何操作返回;如果为 EMPTY_PARCEL 则使用 mMap = new ArrayMap<>(1) 创建长度为 1 的 ArrayMap 对象;如果为 Parcel.obtain() 则实例化 ArrayMap 对象并存储数据。如果本文对您有所帮助,且您手头还很宽裕,欢迎打赏赞助我,以支付网站服务器和域名费用。

5ddf7a299293d.png 您的鼓励与支持是我更新的最大动力,我会铭记于心,倾于博客。

本文链接:https://www.wshunli.com/posts/f0f2eaec.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值