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. Mysql 临时变量的 定义 和 赋值 Set 和 Into 赋值; Swith Mysql版本 Case When的用法

    一:临时变量的定义和赋值 DECLARE spot SMALLINT; -- 分隔符的位置 DECLARE tempId VARCHAR(64); -- 循环 需要用到的临时的Cid DECLARE ...

  2. 【.NET应用技巧】Asp.NET MVC 4 设置IIS下调试

    [环境] VS 2012  IIS7.5 [问题] MVC项目在创建时和APS.NET不同,不能够选择服务器类型,不能够直接把项目创建到IIS上. 如果在项目中直接更改属性,更换调试服务器类型,会报错 ...

  3. fastdfs-client-java 文件上传

    FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储.文件同步.文件访问(文件上传.文件下载)等,解决了大容量存储和负载均衡的问题.特别适合以文件为载体的在线服务,如相 ...

  4. cocos2d_x 问题汇总

    1.生成so文件时,报“No rule to make target ”错误 解决方法:将.\xxx[appname]\proj.android\obj\local\armeabi\objs中的文件全 ...

  5. SSH整合所需jar

    Struts2.1.8+Hibernate3.2+Spring4.1.6+MySql ant-1.6.5.jar ant-antlr-1.6.5.jar ant-junit-1.6.5.jar ant ...

  6. 【栈思想、DP】NYOJ-15 括号匹配(二)

    括号匹配(二) 描述 给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能 ...

  7. Android-取消GridView/ListView item被点击时的效果

    方法一,在控件被初始化的时候设置 gridView.setSelector(new ColorDrawable(Color.TRANSPARENT)); listView.setSelector(ne ...

  8. POJ 2362 Square

    题意:给n个木棍,问能不能正好拼成一个正方形. 解法:POJ1011的简单版……不需要太多剪枝……随便剪一剪就好了……但是各种写屎来着QAQ 代码: #include<stdio.h> # ...

  9. POJ 2386 Lake Counting

    Lake Counting Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 28966   Accepted: 14505 D ...

  10. SQL知识累积

    详细介绍select的文章,展示原始数据.SQL.查询结果,以及在不同数据库下SQL应该如何写. https://en.wikipedia.org/wiki/Select_(SQL) 目录如下: Co ...