Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android編程入門 >> android ipc通信機制之二序列化接口和Binder

android ipc通信機制之二序列化接口和Binder

編輯:Android編程入門

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的聲明。其代碼如下:

 

// 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的各種跨進程通訊方式。

 

 

 

 

 

 

  

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved