进阶之路-多进程-通讯方式之Bundle

526 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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传递的是对象或对象数组时,都需要进行序列化,也就是实现SerializableParcelable接口。

Bundle 通讯示例

MultiProcessActivityAMultiProcessActivityB分别在不同的两个进程里,从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 实现了 CloneableParcelable接口,必定会重载一下方法。

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的本质是对数据进行存储,所以提供了相应的putget的方法,对于其支持的数据类型,他提供了一系列相关的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);
    }