IPC的一些基本概念,Serializable接口,Parcelable接口,以及Binder。此核心为最后的IBookManager.java类!!!

Serializable接口,Parcelable接口都是可以完成对象的序列化过程。

序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

两者均可以实现序列化并且都可以用于Intent数据传递,那么如何的选取:

  Serializable:是Java的序列化接口,使用简单但是开销很大,序列化反序列化过程需要大量I/O操作。

  Parcelable:是Android的序列化接口,更适用于android平台,使用麻烦但是效率高,因此首选Parcelable。

  Parcelable主要用于内存序列化上。若为对象序列化刀存储设备或者将对象序列化后进行网络传输最好使用Serializable,较为简单方便。


Paecelable接口:

 import android.os.Parcel;
import android.os.Parcelable; public class Book implements Parcelable {
int bookid;
String bookname;
public Book(int bookid,String bookname){
this.bookid=bookid;
this.bookname=bookname;
}
//内容描述功能,几乎所有情况都返回“0”,仅当当前对象中存在文件描述符。
//文件描述符在形式上是一个非负整数。实际上,它是一个索引值,
// 指向内核为每一个进程所维护的该进程打开文件的记录表。
@Override
public int describeContents() {
return 0;
}
//序列化功能 writeToParcel,通过Parcel一系列write方法完成。
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(bookid);
dest.writeString(bookname);
}
//反序列化共嗯那个CREATOR,通过Pancel一系列read方法完成。
public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>(){ @Override
public Book createFromParcel(Parcel source) {
return new Book(source);
} @Override
public Book[] newArray(int size) {
return new Book[size];
}
};
private Book(Parcel source){
bookid = source.readInt();
bookname = source.readString();
}
}

Paecelable序列化的过程中需要实现序列化、反序列化、内容描述。

  •    序列化功能 writeToParcel,通过Parcel一系列write方法完成。
  • 反序列化通过CREATOR,通过Pancel一系列read方法完成。 public static final  Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>()
  • 内容描述功能,几乎所有情况都返回“0”,仅当当前对象中存在文件描述符。 
  • 文件描述符:在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。

Binder:

  从android应用层来说,Binder是客户端和服务端进行通讯的媒介,当使用bindSerivice时服务端会返回一个Binder对象,通过这个对象可以获取服务端的服务和数据。

  Android开发中,Binder主要用在Service中,包括AIDL和Messenger,普通的Service中的Binder不涉及进程通信,而Messenger的核心是AIDL,现在新建一个AIDL实例。

AIDL:Android Interface Definition Language,即Android接口定义语言。

创建Book.java,Book.aidl,IBookManager.adil

Book.java:如上述代码。

Book.aidl:在android stuido 可以直接new aidl文件,其作用是Book类在AIDL的声明,(在IBokkManager.aidl文件用到了Book类,就需要声明Book.aidl)。其代码如下:

// Book.aidl
package hang.myapplication; // Declare any non-default types here with import statements parcelable Book;

 IBookManager.adil:是定义的一个接口,包含getBooklist和addBook方法。

注意:尽管Book类和IBookManager在同一包里,但是依然要导入Book类,这是AIDL的特殊之处。与此同时,系统会自动生成IBookManager.java类

之所以使用AIDL,是为了方便系统帮我们生成代码,也可以不借助AIDL自己书写代码,下面有介绍每个方法。。

// IBook.aidl
package hang.myapplication; // Declare any non-default types here with import statements
import hang.myapplication.Book;
interface IBookManager {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
List<Book> getBookList();
void addBook(in Book book);
}

IBook即为IBookManager,在笔者实例中,此处类名与上述名字有差异。
现在,我们就根据这个java类(系统生成的Binder类)分析Binder的工作原理。


IBookeManager.java:

  此处为系统生成代码,较为混乱,可以看文字叙述。核心实现为,内部类stub和其内部代理类proxy。

/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: C:\\Users\\hang\\Documents\\AndroidWorkSpace\\MyApplication\\MyApplication\\IPC\\src\\main\\aidl\\hang\\myapplication\\IBook.aidl
*/
package hang.myapplication;
public interface IBook extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements hang.myapplication.IBook
{
private static final java.lang.String DESCRIPTOR = "hang.myapplication.IBook";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an hang.myapplication.IBook interface,
* generating a proxy if needed.
*/
public static hang.myapplication.IBook asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof hang.myapplication.IBook))) {
return ((hang.myapplication.IBook)iin);
}
return new hang.myapplication.IBook.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getBookList:
{
data.enforceInterface(DESCRIPTOR);
java.util.List<hang.myapplication.Book> _result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook:
{
data.enforceInterface(DESCRIPTOR);
hang.myapplication.Book _arg0;
if ((0!=data.readInt())) {
_arg0 = hang.myapplication.Book.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.addBook(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements hang.myapplication.IBook
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
@Override public java.util.List<hang.myapplication.Book> getBookList() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<hang.myapplication.Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(hang.myapplication.Book.CREATOR);
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public void addBook(hang.myapplication.Book book) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((book!=null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
public java.util.List<hang.myapplication.Book> getBookList() throws android.os.RemoteException;
public void addBook(hang.myapplication.Book book) throws android.os.RemoteException;
}

Binder类

关键方法:

  getBooklist、addBook:这是在IBookManager.aidl中声明的方法,同时在 IBookeManager.java 中为其声明了两个整型的id,分别标识这两个方法。

  内部类Stub:其就是Binder类,当客户端和服务端在同一进程时,方法调用不会走进跨进程的transact过程。而位于不同进程时,则会执行该方法。这个逻辑

        由Stub的内部代理Proxy来完成。

详细介绍: 

  • asInterface:用于将客户端的Binder对象转换成客户端所需要的AIDL接口类型对象,如果客户端和服务端位于同一进程,返回服务端的Stub对象本身。否则,

返回Stub.proxy对象。

  DESCRIPTOR:Binder的唯一标识,一般是当前Binder的类名。

public static hang.myapplication.IBook asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof hang.myapplication.IBook))) {
return ((hang.myapplication.IBook)iin);
}
return new hang.myapplication.IBook.Stub.Proxy(obj);
}
  • asBinder:返回当前Binder对象。
  • boolean onTransact: 全方法为,onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)

          int   code:可以确定客户端的目标方法是什么?可以看到switch case结构。

          android.os.Parcel data:从这里取出目标方法的所需参数(如果目标方法有参数的话)。然后执行目标方法。

          android.os.Parcel reply:目标方法执行完成后,向reply写入返回值(如果目标方法有返回值)。

          以上亦为执行步骤~

          目标方法:此案例getBooklist、addBook就是其中的目标方法。

          若此方法返回false,那么客户端的请求会失败,可利用这一特性做权限验证。

  

  • Proxy#getBooklist和Proxy#addBook:~~~~~~~

          

 若是自定义,记得写上这些方法。         

 

下一章,Android的各种跨进程通讯方式。

  

android ipc通信机制之二序列化接口和Binder的更多相关文章

  1. android ipc通信机制之之三,进程通讯方式。

    IPC通讯方式的优缺点: IPC通讯方式的对比 名称 优点 缺点 适用场景 Bundle 简单易用 只能传输Bundle支持的数据类型 四大组件的进程通信 文件共享 简单易用 不适合高并发场景,并无法 ...

  2. android IPC通信(上)-sharedUserId&amp;&amp;Messenger

    看了一本书,上面有一章解说了IPC(Inter-Process Communication,进程间通信)通信.决定结合曾经的一篇博客android 两个应用之间的通信与调用和自己的理解来好好整理总结一 ...

  3. python 之 并发编程(守护进程、互斥锁、IPC通信机制)

    9.5 守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就立即终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic process ...

  4. Android 进程通信机制之 AIDL

    什么是 AIDL AIDL 全称 Android Interface Definition Language,即 安卓接口描述语言.听起来很深奥,其实它的本质就是生成进程间通信接口的辅助工具.它的存在 ...

  5. Android多线程通信机制

    掌握Android的多线程通信机制,我们首先应该掌握Android中进程与线程是什么. 1. 进程 在Android中,一个应用程序就是一个独立的进程(应用运行在一个独立的环境中,可以避免其他应用程序 ...

  6. android 休眠唤醒机制分析(二) — early_suspend

    本文转自:http://blog.csdn.net/g_salamander/article/details/7982170 early_suspend是Android休眠流程的第一阶段即浅度休眠,不 ...

  7. 架构师成长之路-基于android fragment通信的面向对象的万能接口

    前言 开发一个app时,常用Activity和Fragment,由于操作方便Fragment越来越受欢迎,这样就避免不了Activity和Fragment.Fragment和Fragment之间的通信 ...

  8. Android包管理机制(二)PackageInstaller安装APK

    前言 在本系列上一篇文章Android包管理机制(一)PackageInstaller的初始化中我们学习了PackageInstaller是如何初始化的,这一篇文章我们接着学习PackageInsta ...

  9. Android IPC通信和AIDL技术应用

    首先我们了解一下 IPC和AIDL IPC:进程间通信 AIDL:Android Interface Definition Language,即Android接口定义语言. 为什么使用: Androi ...

随机推荐

  1. poj 1201 Intervals(差分约束)

    做的第一道差分约束的题目,思考了一天,终于把差分约束弄懂了O(∩_∩)O哈哈~ 题意(略坑):三元组{ai,bi,ci},表示区间[ai,bi]上至少要有ci个数字相同,其实就是说,在区间[0,500 ...

  2. Oracle数据文件管理

    1.数据文件概述 Oracle数据库的数据文件(扩展名为DBF的文件)是用于保存数据库中数据的文件,系统数据.数据字典数据.临时数据.索引数据.应用数据等都物理地存储在数据文件中.用户对数据库中数据的 ...

  3. HDU 1863 畅通工程(最小生成树,prim)

    题意: 给出图的边和点数,要求最小生成树的代价,注:有些点之间是不可达的,也就是可能有多个连通图.比如4个点,2条边:1-2,3-4. 思路: 如果不能连通所有的点,就输出‘?’.之前以为每个点只要有 ...

  4. Log4NET简介

    log4net库是Apache log4j框架在Microsoft .NET平台的实现,是一个帮助程序员将日志信息输出到各种目标(控制台.文件.数据库等)的工具. 前提 最近做项目需要记录系统日志和用 ...

  5. 编译boost (windows msvc14)

    我的环境 OS: WIN10 (x64) IDE: VS2015 (VC14) http://www.boost.org/ 1. 下载 下载boost包, boost_1_62_0.7z 使用ASIO ...

  6. MultiSet

    Guava引进了JDK里没有的,但是非常有用的一些新的集合类型.所有这些新集合类型都能和JDK里的集合平滑集成.Guava集合非常精准地实现了JDK定义的接口.Guava中定义的新集合有: Multi ...

  7. Metaspace 之二--Java 8的元空间(metaspace)、metaspace监控方法

    很多开发者都在其系统中见过“java.lang.OutOfMemoryError: PermGen space”这一问题.这往往是由类加载器相关的内存泄漏以及新类加载器的创建导致的,通常出现于代码热部 ...

  8. codevs1796-最小完全图

    表示第一篇就是水题. 根据Prim的思想,我们可以证明:dis ( a , b ) > max { a b 最小生成树路径上的边权 } 把所有边sort一遍用并查集维护就可以了 #include ...

  9. jedis入门实例

    在使用传统的关系数据库,我们都需要依赖一个所谓的实现了jdbc规范的驱动程序来连接数据库,这些驱动程序由各大数据库厂商提供.这些驱动就是jar包,里面就是封装了对数据库的通信协议,我们通过简单的调用就 ...

  10. HDU 5311

    把anniversary分成三个区间,分别枚举每个区间在给定模板中的长度.每次枚举完一个区间,记录下区间长度和起始坐标,下次从剩下长度开始枚举,避免重复. #include<iostream&g ...