从源码剖析Android中的Intent组件

2019-12-10 18:49:29于海丽

四、核心问题:为何Intent不能直接在组件间传递对象而要通过序列化机制?
根据上面代码可以看到,Intent在启动其他组件时,会离开当前应用程序进程,进入ActivityManagerService进程(intent.prepareToLeaveProcess()),这也就意味着,Intent所携带的数据要能够在不同进程间传输。首先我们知道,Android是基于Linux系统,不同进程之间的java对象是无法传输,所以我们此处要对对象进行序列化,从而实现对象在 应用程序进程 和 ActivityManagerService进程 之间传输。
而Parcel或者Serializable都可以将对象序列化,其中,Serializable使用方便,但性能不如Parcel容器,后者也是Android系统专门推出的用于进程间通信等的接口。

附加知识:
在不同进程之间,常规数据类型可以直接传递,如整数,以传递字符串为例,要从A进程传递到B进程,只需在B进程的内存区开辟一样大小的空间,然后复制过去即可。
但是,对象却不能直接跨进程传递。即使成员变量值能传递过去,成员方法是无法传递过去的,此时如果B进程要调用成员方法则出错。
具体传递对象的方法:
1. 在进程A中把类中的非默认值的属性和类的唯一标志打成包(这就叫序列化);
2. 把这个包传递到进程B;
3. 进程B接收到包后,根据类的唯一标志把类创建出来(java反射机制);
4. 然后把传来的属性更新到类对象中。
这样进程A和进程B中就包含了两个完全一样的类对象。

五、Intent如何实现对象传递?
Object implements Serializable {...};bundle.putSerializable(Key, Object); 
Object implements Parcelable {...} ; bundle.putParcelable(Key, Object);
Serializable接口:这是Java的序列化技术,将Java对象序列化为二进制文件。让对象实现Serializable接口,使用ObjectInputStream 和 ObjectOutputStream 进行对象读写。
Parcelable接口:这是Android提供的用作封装数据的容器,封装后的数据可以通过Intent或IPC来传递。只有基本类型和实现了Parcelable接口的类才能被放入Parcel中。
六、Serializable接口 - Java
属于java序列化机制:只需让java类实现该接口,不用实现任何方法,即可标记该类可序列化。

class Person implements Serializable {...}
Person per = new Person();
bundle.putSerializable("person", per); //传递Person对象的引用

Person mPerson = (Person)getIntent().**getSerializableExtra**("person");