編輯:關於Android編程
前段時間一直在看有關Binder的知識,最近剛好有時間,總結一些一些知識,希望和大家交流學習。
說起Binder我相信大家學android開發的多多少少都對binder有些了解,binder機制作為android進程間通信的一種機制,在Android底層中應用的非常多。我們都知道Android系統是基於LInux內核開發的,Linux內核提供了豐富的進程間通信的機制,如:管道、信號、消息隊列、共享內存和套接字等,但是Android系統並沒有采用傳統的進程間通信機制,而是開發了一套新的進程間通信的機制BInder,當然采用Binder肯定有一些優勢,與傳統的進程間通信相比,BInder進程通信機制在進程間傳輸數據的時候,只需要執行一次拷貝操作,因此,在效率和內存節省方面有一定的優勢。
接下來我們就開始談談Binder了,Binder說白了就是Android中的一個類,它實現了Ibinder接口,從Android-Framework角度來說,Binder是ServiceManager連接各種Manager(ActivityManager、WindowManager等)和相應的Manager_Service的橋梁;下面有一張他們之間的圖
Binder在進行進程間通信的時候,每一個Server進程和Client進程都維護一個Binder線程池來處理進程間的通信要求,Service組件在啟動時,會將自己注冊到一個Service Manager組件中,以便Client組件可以通過Service Manager組件找到它。上圖中Binder驅動程序和Service Manager由系統提供,Client和Service由應用程序實現,接下來我已我們Android中最常用的AIDL為例討論一下
編寫一個AIDL程序需要以下幾步:
首先我們看看服務端程序需要的步驟:
(1)首先編寫你的類(book.java)文件,這個類必須實現Parcelable接口進行序列化。
(2)編寫與該類相同的名的aidl文件(book.aidl)
(3)編寫接口文件(IBookManager.aidl),此接口即客戶端請求時的接口
(4)實現服務端的service(BookManagerService),該service為客戶端實際進行服務(主要實現Stub類)
接下來我們看看客戶端要實現的步驟:
客戶端其實與服務端很多地方相似:
(1)我們這一塊需要將服務端的所有AIDL文件拷貝帶客戶端,這裡的報名必須與服務端一致,因為存在序列化與反序列化問題
(2)編寫客戶端Activity,綁定服務端service
(3)實現ServiceConnection,在onServiceConnected方法中,將講IBinder轉化為AIDL接口類型,然後調用遠程服務
(4)如果遠程服務比較耗時,可以將調用方法從主線程中分離出來,開一個子線程,這樣程序就不會崩潰
好吧,大家現在估計也是很懵逼的吧,我再給大家理一遍然後就上代碼了:
首先大家可以看到,當我們新建一個AIDL文件之後,在gen文件夾下會生成一個對應的AIDL文件,他是系統為我們自動生成的一個接口類,繼承自android.os.IInterface接口,其中有幾個比較重要的類和方法這裡我給大家一一說明:
首先是stub類,這個Stub類繼承BInder實現了我們定義的AIDL接口,這個類也是我們客戶端在實際要用到的類,在這個類中有一個asInterface方法,他的參數是一個IBinder接口,他返回了另一個Stub的內部類proxy,這個proxy類真正實現了AIDL接口,每當客戶端通過Stub的asInterface方法獲取到該類時,調用具體的接口方法時,proxy類裡面會調用transact,當客戶端和服務端都位於一個進程時,方法調用就不會走跨進程的transact過程,如果不在同一個進程的話將會交給Proxy的處理,這裡transact有幾個參數第一個參數為請求的方法類型,接下來_data與_reply他們兩個是一個parcel類型,其中分別封裝客戶端的請求信息和服務端反饋的信息,然後底層通過Bindler傳送到onTransact方法中,他會從客戶端傳過來的參數中判斷客戶端請求的是那個方法,裡面的請求信息是什麼,接下來會將數據寫入,返回到客戶端。
上面就是BInder跨進程的的整個流程,下面就是上代碼了:
AIDL文件
Book.java package com.binderpro.aidl; import android.os.Parcel; import android.os.Parcelable; public class Book implements Parcelable{ private String name; private int price; private int bookId; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public Book(String name, int price) { super(); this.name = name; this.price = price; } @Override public String toString() { return "Book [name=" + name + ", price=" + price + "]"; } @Override public int describeContents() { // TODO Auto-generated method stub return 0; } @Override public void writeToParcel(Parcel arg0, int arg1) { // TODO Auto-generated method stub arg0.writeInt(bookId); arg0.writeString(name); arg0.writeInt(price); } public static final Parcelable.CreatorCREATOR = new Parcelable.Creator (){ @Override public Book createFromParcel(Parcel arg0) { // TODO Auto-generated method stub return new Book(arg0); } @Override public Book[] newArray(int arg0) { // TODO Auto-generated method stub return new Book[arg0]; } }; private Book(Parcel in){ bookId = in.readInt(); name = in.readString(); price = in.readInt(); } }
Book.aidl package com.binderpro.aidl; parcelable Book;
IBookManager
package com.binderpro.aidl; import java.util.List; import com.binderpro.aidl.Book; interface IBookManager { ListgetBookList(); void addBook(in Book book); }
BookManagerService
package com.example.binderpro; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import com.binderpro.aidl.Book; import com.binderpro.aidl.IBookManager; public class BookManagerService extends Service { private static final String TAG = "BMS"; private CopyOnWriteArrayListmBookList = new CopyOnWriteArrayList (); public BookManagerService() { // TODO Auto-generated constructor stub } private Binder mBinder = new IBookManager.Stub() { @Override public List getBookList() throws RemoteException { // TODO Auto-generated method stub return mBookList; } @Override public void addBook(Book book) throws RemoteException { // TODO Auto-generated method stub mBookList.add(book); } }; @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); mBookList.add(new Book("android", 1)); mBookList.add(new Book("ios", 2)); } public IBinder onBind(Intent intent){ return mBinder; } }
MainActivity.java
package com.example.binderpro; import java.util.List; import com.binderpro.aidl.Book; import com.binderpro.aidl.IBookManager; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.util.Log; import android.view.Menu; public class MainActivity extends Activity { private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName arg0) { // TODO Auto-generated method stub } @Override public void onServiceConnected(ComponentName arg0, IBinder arg1) { // TODO Auto-generated method stub IBookManager bookManager = IBookManager.Stub.asInterface(arg1); Listlist; try { list = bookManager.getBookList(); Log.i("Tag", list.toString()); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent("com.example.binderpro.BookManagerService"); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); unbindService(mConnection); } }
IBookManager代碼比較長,我刪除了一部分
/* * This file is auto-generated. DO NOT MODIFY. * Original file: G:\\android_code\\Binderpro\\src\\com\\binderpro\\aidl\\IBookManager.aidl */ package com.binderpro.aidl; public interface IBookManager extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.binderpro.aidl.IBookManager { private static final java.lang.String DESCRIPTOR = "com.binderpro.aidl.IBookManager"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.binderpro.aidl.IBookManager * interface, generating a proxy if needed. */ public static com.binderpro.aidl.IBookManager asInterface( android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.binderpro.aidl.IBookManager))) { return ((com.binderpro.aidl.IBookManager) iin); } return new com.binderpro.aidl.IBookManager.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_result = this .getBookList(); reply.writeNoException(); reply.writeTypedList(_result); return true; } case TRANSACTION_addBook: { data.enforceInterface(DESCRIPTOR); com.binderpro.aidl.Book _arg0; if ((0 != data.readInt())) { _arg0 = com.binderpro.aidl.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 com.binderpro.aidl.IBookManager { private android.os.IBinder mRemote; @Override public java.util.List getBookList() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.util.List _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0); _reply.readException(); _result = _reply .createTypedArrayList(com.binderpro.aidl.Book.CREATOR); } finally { _reply.recycle(); _data.recycle(); } return _result; } @Override public void addBook(com.binderpro.aidl.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); } }
最近看到身邊的很多android開發程序員都在使用android studio,於是自己也下了個嘗試怎麼使用。其實這個開發工具在2013年我就知道了,那時由於自己太懶了,
運行效果 這篇博客還是接著上一篇Android音樂播放器制作寫的,沒看過的可以去看看其中這個效果(圓形ImageView和控件勻速旋轉):我前面的博客中寫到過我
其實Android移動端也存在類似的套路,下面小編為各位寶寶們來剖他一析我一探究竟!最簡單的盜號QQ開發流程,你值得擁有,吼吼~~~項目名稱: 定制盜號QQ期望結果: 用
問題背景:在做圖表展示的時候,ListView可以上下左右滑動,但最左邊一列在向右滑動時,保持不變,表頭在向下滑動時保持不變。有用兩個ListView實現的,但測試過,好