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. Java [Leetcode 229]Bulls and Cows

    题目描述: You are playing the following Bulls and Cows game with your friend: You write down a number an ...

  2. Java [Leetcode 118]Pascal's Triangle

    题目描述: Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5 ...

  3. noip2006提高组题解

    第一题:能量项链 区间型动态规划 据说这题在当年坑了很多人. f(i, j) 表示从第i个珠子开始合并j个珠子所释放的最大能量. f(i, j) = max{ f(i, k} + f(i+k, j-k ...

  4. windows下MySql没有setup.exe时的安装方法

    01.把 mysql-advanced-5.6.17-winx64.zip 解压到自定义 D:\mysql-5.6.17-W64 或 D:\mysql-advanced-5.6.17-winx64 目 ...

  5. html input readonly 和 disable的区别

    Readonly和Disabled它们都能够做到使用户不能够更改表单域中的内容.但是它们之间有着微小的差别,总结如下: Readonly只针对input(text / password)和textar ...

  6. Android UncaughtExceptionHandler,捕获错误

    最近在做个项目,需要在程序出现运行时异常和错误导致程序crash时进行一些操作,找到一个方法 Thread.setDefaultUncaughtExceptionHandler(new Uncaugh ...

  7. Android-AnimationDrawable(一)

    大家平时见到的最多的可能就是Frame动画了,Android中当然也少不了它.它的使用更加简单,只需要创建一个 AnimationDrawabledF对象来表示Frame动画,然后通过addFrame ...

  8. u-boot 源码修改 bootcmd,IP ,BOOTARGS等参数

    uboot1.1.6\include\configs\smdk6410.h #define CONFIG_BOOTCOMMAND"nand read 0xc0008000 0x200000 ...

  9. 【转】如何用WINDBG分析64位机上32位程序的DUMP文件

    将dump拖入到windbg中后,在command输入栏输入 .load wow64exts 回车 !sw 回车,就将windbg的dump,从64位模式切换到了32位模式,否则看到的call sta ...

  10. hdu 2459 (后缀数组+RMQ)

    题意:让你求一个串中连续重复次数最多的串(不重叠),如果重复的次数一样多的话就输出字典序小的那一串. 分析:有一道比这个简单一些的题spoj 687, 假设一个长度为l的子串重复出现两次,那么它必然会 ...