前言

Android的AIDL不仅可以在绑定服务中传递一些Android规定的数据类型的数据,还可以传递一些复杂类型的数据。但是与传递系统允许的数据类型相比,复杂类型数据的传递要做更多的工作,本篇博客就讲解一下如何使用AIDL接口通过绑定服务在进程间传递数据。关于AIDL传递规定类型数据的内容,不了解的朋友可以看看之前的博客:AIDL传递系统允许类型数据。

本篇博客的主要内容:

AIDL传递复杂类型对象的特殊处理

前面已经介绍了通过AIDL接口在进程间传递系统允许的数据,如果需要传递一个复杂类型的对象,就没那么简单了,需要额外做一些处理。如下:

定义数据接口的AIDL文件中,使用parcelable关键字,例如:parcelable Message;

在其数据实现类中实现Parcelable接口,并实现对应的方法。

在业务接口的AIDL文件中,使用import引入数据接口AIDL的包名。

例如:Message.aidl

1 parcelable Message;

例如:IGetMsg.aidl

1 package com.example.aidlservicedemo.domain;

2

3 // 这是两个自定义类

4 import com.example.aidlservicedemo.domain.Message;

5 import com.example.aidlservicedemo.domain.User;

6

7 interface IGetMsg{

8 // 在AIDL接口中定义一个getMes方法

9 List getMes(in User us);

10 }

Parcelable与Parcel接口

先来说说Android对象序列化,在Android中序列化对象主要有两种方式,实现Serializable接口或是实现Parcelable接口。Serializable接口是JavaSE原生支持的,而Parcelable接口是Android所特有的,它的序列化和反序列化的效率均比Serializable接口高,而AIDL进行在进程间通信(IPC),就是需要实现这个Parcelable接口。

Parcelable接口的作用:实现了Parcelable接口的实例,可以将自身的数据信息写入一个Parcel对象,也可以从parcel中恢复到对象的状态。而Parcel就是完成数据序列化写入的载体。

上面提到Parcel,再来聊聊Parcel是什么?Android系统设计之初,定位就是针对内存受限的设备,因此对性能要求更好,所以系统中采用进程间通信(IPC)机制,必然要求性能更优良的序列化方式,所以Parcel就被设计出来了,其定位就是轻量级的高效的对象序列化机制与反序列化机制。如果读一下Android的底层代码,会发现Parcel是使用C++实现的,底层直接通过Parcel指针操作内存实现,所以它的才更高效。

Parcel也提供了一系列的方法帮助写入数据与读取数据,这里简单介绍一下:

obtain():在池中获取一个新的Parcel。

dataSize():得到当前Parcel对象的实际存储空间。

dataPostion():获取当前Parcel对象的偏移量。

setDataPosition():设置当前Parcel对象的偏移量。

recyle():清空、回收当前Parcel对象的内存。

writeXxx():向当前Parcel对象写入数据,具有多种重载。

readXxx():从当前Parcel对象读取数据,具有多种重载。

简单来说,Parcelable通过writeToParcel()方法,对复杂对象的数据写入Parcel的方式进行对象序列化,然后在需要的时候,通过其内定义的静态属性CREATOR.createFromParcel()进行反序列化的操作。Parcelable对Parcel进行了包装,其内部就是通过操作Parcel进行序列化与反序列化的。

Parcelable与Parcel均定义在android.os包下,而这种机制不仅用于AIDL,还可以用于Intent传递数据等其他地方,这不是本篇博客的主题,以后用到再详细介绍。

实现Parcelable接口

定义好数据接口的AIDL文件后,需要定义一个数据实现类,实现Parcelable接口,并实现对应的方法,Parcelable有如下几个必须要实现的抽象方法:

abstract int describeContents():返回一个位掩码,表示一组特殊对象类型的Parcelable,一般返回0即可。

asbtract void writeToParcel(Parcel dest,int flags):实现对象的序列化,通过Parcel的一系列writeXxx()方法序列化对象。

除了上面两个方法,还需要在实现类中定义一个名为"CREATOR",类型为"Parcelable.Creator"的泛型静态属性,它实现了对象的反序列化。它也有两个必须实现的抽象方法:

abstract T createFromParcel(Parcel source):通过source对象,根据writeToParcel()方法序列化的数据,反序列化一个Parcelable对象。

abstract T[] newArray(int size):创建一个新的Parcelable对象的数组。

例如:

1 @Override

2 public int describeContents() {

3 return 0;

4 }

5

6 @Override

7 public void writeToParcel(Parcel dest, int flags) {

8 Log.i("main", "服务端Message被序列化");

9 dest.writeInt(id);

10 dest.writeString(msgText);

11 dest.writeString(fromName);

12 dest.writeString(date);

13 }

14

15 public static final Parcelable.Creator CREATOR = new Creator() {

16

17 @Override

18 public Message[] newArray(int size) {

19 return new Message[size];

20 }

21

22 @Override

23 public Message createFromParcel(Parcel source) {

24 Log.i("main", "服务端Message被反序列化");

25 return new Message(source.readInt(), source.readString(),

26 source.readString(), source.readString());

27 }

28 };

从上面示例中可以看出,使用writeToParcel()方法进行序列化,通过CREATOR.createFromParcel进行反序列化,它们都传递一个Parcel类型的对象,这里要注意的是两个方法中Parcel对象的writeXxx()和readXxx()方法的顺序必须一致,因为一般序列化数据是以链的形式序列化的,如果顺序不对,反序列化的数据会出错。

AIDL传递复杂类型对象Demo

关键点已经讲到, 下面通过一个简单的Demo来演示AIDL传递复杂对象。

AIDL接口:

com.example.aidlservicedemo.domain.Message.aidl

 Message.aidl

com.example.aidlservicedemo.domain.Message.java

 Message.java

com.example.aidlservicedemo.domain.User.aidl

 User.aidl

com.example.aidlservicedemo.domain.User.java

 User.java

服务:

com.example.aidlservicedemo.

 CustomTypeService.java

客户端:

com.example.aidlClientdemo.

 CustomTypeActivity.java

效果展示:

AIDL传递对象序列化过程详解

通过上面Demo打印的日志,解释一下序列化的过程,打开Logcat查看日志。

从上图的PID列可以看出这是两个线程间的交互。

流程是这样的,客户端传递一个User对象给服务端,服务端通过User对象处理数据,返回两个Message对象给客户端。

首先,在客户端传递给服务端User对象前,客户端先把User对象序列化,然后传递给服务端之后,服务端接收到的是一段序列化后的数据,它再按照原定的规则对数据进行反序列化,然后处理User。当服务端查到这个User有两条Message时,需要传递这两条Message对象给客户端,在传递前对Message对象进行序列化,客户端收到服务端传递过来的序列化后的数据,再根据既定的规则进行反序列化,得到正确的对象。

从这个流程可以看出,在进程间传递的数据必定是被序列化过的,否则无法传递。而对于那些AIDL默认允许传递的数据类型(int、double、String、List等),它们其实内部已经实现了序列化,所以无需我们再去指定序列化规则。但是对于复杂类型对象而言,系统无法知道如何去序列化与反序列化,所以需要我们指定规则。

android--service之aidl传递复杂对象,Android--Service之AIDL传递复杂对象相关推荐

  1. android activity之间传递对象,Android Activity之间的数据传递

    一.通过startActivity来进行Activity的传值 在Android中,如果我们要通过一个Activity来启动另一个Activity,可以使用 startActivity(Intent ...

  2. Android service 和 client的进程通信和消息回调--AIDL

    2019独角兽企业重金招聘Python工程师标准>>> (一)项目介绍 Launcher上播放小视屏和独立的视频应用.小视屏是视频应用的裁剪版,只有播放的功能,两者使用相同的底层系统 ...

  3. Android Studio开发基础之启动Service,并通过从Activity向Service传递数据

    本实例演示启动Service,并通过从Activity向Service传递数据,新建一个Service,并敲如下代码: package com.example.lhb.startservice;imp ...

  4. android 启动服务同时传递数据,Android Studio开发基础之起动Service,并通过从Activity向Service传递数据...

    Android Studio开发基础之启动Service,并通过从Activity向Service传递数据 本实例演示启动Service,并通过从Activity向Service传递数据,新建一个Se ...

  5. android handler 传递对象,Android之Handler消息传递机制详解

    前言 在Android开发中,多线程应用是非常频繁的,其中Handler机制随处可见. 下面就本人对Handle的一些理解与大家一起分享,共同回顾下Handle异步消息传递机制. 1.Handler是 ...

  6. android bundle 对象,Android Bundle传递对象

    首先Android的Bundle是可以传递对象的.我们可以用Bundle b = new Bundle():b.putSerializable("key", 对象引用); 但是这样 ...

  7. android传递socket对象,Android Socket通信详解

    一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是"请求-响应方式",即在请求时 ...

  8. android studio 跨进程,Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用...

    本文首发于微信公众号「后厂技术官」 在上一篇文章Android IPC机制(二)用Messenger进行进程间通信中我们介绍了使用Messenger来进行进程间通信的方法,但是我们能发现Messeng ...

  9. Android开发笔记(五十三)远程接口调用AIDL

    AIDL概述 AIDL全称是"Android Interface Definition Language",即Android的接口定义语言.AIDL用来协助开发者来处理进程间通信, ...

  10. 【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 七 )

    Android 事件分发 系列文章目录 [Android 事件分发]事件分发源码分析 ( 驱动层通过中断传递事件 | WindowManagerService 向 View 层传递事件 ) [Andr ...

最新文章

  1. BZOJ 1996 [Hnoi2010]chorus 合唱队
  2. 用开源的人工标注数据来增强RoFormer-Sim
  3. Maven常用的构建命令
  4. 记一次,jvm 内存溢出
  5. 网络抓包工具wireshark 安装教程
  6. 解决谷歌浏览器重复上传同一文件失败的问题
  7. python 绘制降水量色斑图
  8. IDEA eclipse快捷键大全
  9. Android平台语言支持状态(MTK6589)
  10. raise notice oracle,openGauss 循序渐进:通过 raise notice 模拟 Oracle 的 DBMS_OUTPUT
  11. 服务器安装系统关闭磁盘阵列,戴尔服务器H330阵列卡取消磁盘阵列教程
  12. 如何从零创造一个围棋AI
  13. Tivoli Workload Scheduler (TWS)
  14. 编码——隐匿在计算机软硬件背后的语言上
  15. win7系统中的消息队列服务器,高手分析win7系统安装消息队列的详细
  16. termux 安装 kali
  17. 中国最好的职业TOP10
  18. 静力触探CPT处理及表层声速异常处理记录
  19. 计算机网络语音传输杂音回音,一种用于消除网络声音传输的回音和啸叫的系统和方法与流程...
  20. 按现在的政策灵活就业人员,还有没有必要每年自己缴纳养老保险?

热门文章

  1. 3DSlicer14:Loadable Module
  2. VTK修炼之道44:图形进阶_vtkPolyData数据源讨论与数据创建
  3. Delphi中TFlowPanel实现滚动条效果
  4. javascript事件驱动框架 收藏
  5. 【CyberSecurityLearning 28】批处理与简单病毒
  6. TCP listen() Backlog 参数详解
  7. java中继承、多接口实现
  8. 手写简版spring --9--对象作用域和FactoryBean
  9. STM32开发 -- cannot open source input file absacc.h 解决方法
  10. 【译】Understanding Linked Data Formats