• IPC机制(二)


    copy from :https://www.jianshu.com/p/dee1cad7b761

    前言:Serializable和Parcelable接口可以完成对象的序列化过程,当我们需要通过Intent和Binder传输数据时就需要使用Parcelable或者Serializable。还有的时候我们需要把对象持久化到存储设备上或者通过网络传输给其他客户端,这个时候也需要Serializable来完成对象的持久化。

    一:Serializable接口

            Serializable是Java提供的一个序列化接口,它是一个空接口,为对象提供标准的系列化和反序列化操作。想让一个对象实现序列化,只要这个类实现Serializable接口并声明一个serializableUID即可,实际上,甚至这个serializableUID也不是必须的,我们不声明这个serializableUID同样也可以实现序列化,但是这将会对序列化过程产生影响。

            通过Serializable方式来实现对象序列化,实现起来非常简单,几乎所有的工作都被系统自动完成了。如何进行对象序列化和反序列化也非常简单,只需要采用ObjectOutputStream和ObjectInputStream即可轻松实现。

     
    序列化和反序列化

             只需要把实现了Serializable接口的User对象写到文件中就可以快速恢复了,恢复后的对象newUser和user的内容完全一样,但是两者并不是一个对象。这个serializableUID是用来辅助序列化和反序列化过程的,原则上序列化后的数据中的serializableUID只有和当前类的serializableUID相同才能正常地被反序列化。serializableUID的详细工作机制是这样的:序列化的时候系统会把当前类的serializableUID写入序列化的文件中(也可能是其他的中介),当反序列化的时候系统会去检测文件中的serializableUID,看它是否和当前类的serializableUID一致,如果一致说明序列化的类的版本和当前类的版本是相同的,这个时候可以成功反序列化;否则就说明当前类和序列化的类相比发生了某些交换,比如成员变量的数量、类型可能发生了改变,这个时候是无法正常序列化的。

              一般来说,我们应该手动指定serializableUID的值,比如1L,也可以让AndroidStudio根据当前类的结构自动去生成它的hash值,这样序列化和反序列化时两者的serializableUID是相同的,因此可以正常的进行反序列化。如果不手动指定serializableUID的值,反序列化时当前类有所改变,比如增加了或者删除了某些成员变量,那么系统就会重新计算当前类的hash值并把它赋值给serializableUID,这个时候当前类的serializableUID就和序列化数据中的serializableUID不一致,于是反序列化失败,程序就会出现crash。所以,serializableUID的作用明显的,当我们手动指定它以后,就可以在很大程度上避免反序列化过程的失败。以下两点需要特别提出:首先静态成员变量属于类不属于对象,所以不会参与序列化过程;其次用transient关键字标记的成员变量不参与序列化过程。

    附:title:Intellij IDEA 自动生成 serialVersionUID

    1-》进入操作

    AndroidStudio->Preference->Inspections->Serialization issues->Serializable class without ’serialVersionUID’ ->勾选操作

    2-》执行操作设置之后,当创建一个类并实现Serializable之后,在你的类名上:Alt+Enter就会提示自动创建serialVersionUID。

     
    图示操作

    二、Parcelable接口

             Parcelable也是一个接口,只要实现这个接口,一个类的对象就可以实现序列化并可以通过Intent和Binder传递。

     
    典型的用法

           系统已经为我们提供了许多实现Parcelable接口的类,它们都是可以直接序列化的,比如Intent、BundlBitMap等,同时List和Map也可以进行序列化,前提是它们里面的每个元素都是可序列化的。

     
    Parcelable和 Serializable的比较

    三、Binder

            侧重介绍Binder的使用以及上层原理。从Android应用层来说,Binder是客户端和服务器端进行通信的媒介,当bindService的时候,服务端会返回一个包含了服务端业务的调用的Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务。Android开发中,Binder主要用在Service中,包括AIDL和Messager,其中普通的Service中的Binder不涉及进程间通信,所以较为简单,无法触及Binder的核心,而Messenger的底层其实就是AIDL。

    Android Studio 中如何创建AIDL:实现客户端添加Book,Service接收并打印出书籍信息。

    1.创建Book类并继承Parcelable接口(原因:AIDL只能传递继承Parcelable接口的类)

     
    Book.java

    2.创建AIDL文件夹与Book.aidl

           用AIDL File填写名字的时候先随便填写(因为如果直接填Book为名字时候会报错,只有先创建完之后再RENAME才不会报错! 为什么要有Book.aidl类?因为只有将类在aidl中声明时候,AIDL才能调用Book类,接下来为如何声明:

     
    Book.aidl

          所以说要AIDL能够传递自定义类需要1)继承Parcelable接口;2)创建同名.aidl文件声明自己。

    3.创建IBookManager.aidl(作用:设置让客户端允许调用的接口)

     
    IBookManager.aidl

    4.分析Binder的运行原理

    注释:Stub对象可以理解为Binder类

    1.系统自动生成IBookManager.java文件在

     
    IBookManager.java

    分析其属性和方法:

    1)DESCRIPTOR:Binder的唯一标识,一般用当前Binder的类名表示,比如:

    private static final String DESCRIPTOR ="com.bignerdranch.android.photogallery.androidart.IBookManager";

    2)asInterface(IBinder obj):将服务端的Binder对象转成客户端的所需的AIDL对象。

    ①:若客户端与服务端在同一进程则返回服务端的Stub本身。

    ②:若客户端与服务端在不同进程则返回的是Stub.proxy对象。

    3)asBinder():返回当前的Binder对象

    4)onTransact():当客户端发起跨进程请求时,会调用此方法,返回Stub.proxy

    5)Proxy#getBookList()和 Proxy#addBook():我们刚才创造的接口。

     
    Binder的工作原理
     
    附图

           最后,我们简单介绍Binder的两个很重要的方法linkToDeath和unlinkToDeath.Binder运行在服务端进程,如果服务端进程由于某种原因异常终止,这个时候我们到服务端的Binder链接断裂(称之为Binder死亡),会导致我们的远程调用失败,更为关键的是,如果不知道Binder链接已经断裂,那么客户端的功能就会受影响。为了解决这个问题,Binder中提供了两个配对的方法linkToDeath和unlinkToDeath,通过linkToDeath,我们可以给Binder设置一个死亡代理,当Binder死亡时,我们就会收到通知,这个时候我们就可以重新发起链接请求从而恢复连接。



    作者:熊出没之大熊快跑
    链接:https://www.jianshu.com/p/dee1cad7b761
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    Always Believe Something Beauitful Will Be Happen
  • 相关阅读:
    ActionScript 条件编译
    FLASH通讯小结
    关于ob_start()
    剖析PHP中的输出缓冲
    Ext.app.controller的refs
    php多线程解决之stream_socket_client
    谷歌的JQuery库
    PHP计划任务之关闭浏览器后仍然继续执行的函数
    关于php调用可执行程序,在后台运行而不让页面等待
    把预定义的字符串转化为html标签
  • 原文地址:https://www.cnblogs.com/Oude/p/12435982.html
Copyright © 2020-2023  润新知