<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ### 一,什么是IPC IPC:inter-process communication,進程間通信或者跨進程通信。window通過剪貼板,管道等進行進程間通信。Linux通過命名管道,共享內存,信號量等進行進程間通信。android有特色的是Binder。在android進程通信可以有以下方式:aidl,socket通信,使用Bundle,使用contentprovider,使用Messenger,使用文件共享。 ### 二,android的序列化 在android中能用于進程間通信的對象必須是序列化的。序列的方式有兩種,一種是實現Serializable接口,一種是實現Parcelable。Serializable是java提供的序列化方法,實現很簡單,只要一個類實現了它就完成了序列化。可用于將對象序列化到存儲設備或序列化后通過網絡傳輸。但它的效率不高,這里重點介紹Parcelable,它是android自己的實現序列化方法,先看實現Parcelable的代碼: 只要一個類實現了這個接口,就可以實現序列化并可以通過Intent和Binder傳遞。要實現以下方法 (1).writeToParcel(out,flags):實現序列化功能,一系列write。如下 out.writeInt(userId); out.writeParcelable(book,0);//傳另一個序列化類 (2).CREATOR:反序列化,一系列的read方法:如下 userId = in.readInt(); book = in.readParcelable(Thread.currentThread().getContextClassLoader()); (3).decribeContents:內容描述,幾乎所有情況都返回0. 完整代碼如下 ~~~ public class Book implements Parcelable { public int bookId; public String bookName; public Book() { } public Book(int bookId, String bookName) { this.bookId = bookId; this.bookName = bookName; } public int describeContents() { return 0; } public void writeToParcel(Parcel out, int flags) { out.writeInt( bookId); out.writeString( bookName); } public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() { public Book createFromParcel (Parcel in) { return new Book(in); } public Book[] newArray( int size) { return new Book[size]; } }; private Book(Parcel in) { bookId = in.readInt(); bookName = in.readString(); } @Override public String toString() { return String.format("[bookId:%s, bookName:%s]" , bookId , bookName); } } ~~~ 系統還提供了一些實現了Parcelable接口的類,如Intent,Bundle,Bitmap.同時List和Map也可以序列化,前提是它們里所有元素都 可以序列化。 Parcelable效率比Serializable高,在內存序列化上用它合適。但在將對象序列化到存儲設備或序列化后通過網絡傳輸則建議用Serializable,比較方便。 ### 三,Binder的介紹 Binder用于完成進程間的通信(IPC)。Binder是工作在Linux層,屬于一個驅動,這個驅動不需要驅動,Binder代碼運行在內核態,調用Binder是系統進行調用。 Binder是一種架構,這種架構提供服務端接口,Binder?接口,客戶端接口三個模塊。一個Binder?服務端就是一個Binder對象,該對象一旦創建,就會啟動一個隱藏線程,該線程會接Binder?驅動發送的消息。收到消息會發調用 onTransact()方法,并按照參數執行不同的服務代碼,onTransact()?的參數來源是客戶端調用 transact(),若transact()?有固定的輸入,onTransact()就有固定的輸出 。 一個服務端被創建,會創建一個mRemote對象,它的類型也是Binder類,客戶端要訪問遠程時是通過它。它也重載了transact()方法,重載內容如下: 1,以線程消息通信模式,向服務端發送客戶端傳遞過來的參數。 2.掛起當前線程,并等待服務端線程執行完指定服務函數后通知。 3.接收服務端通知并執行客戶端線程,并返回到客戶端代碼區。 它的調用圖如下: ![](https://box.kancloud.cn/2016-04-08_570771b55b898.jpg) 接下來我們來看看如何使用它。 新建兩個文件Book.aidl,IBookManager.aidl,其中Book.aidl是上面序列化后文件的一個聲明,主意名稱要和序列化的類的名稱一樣。內容如下: ~~~ package com.lxj.aidl; parcelable Book; ~~~ 再看下IBookManager.aidl,這個demo主要實現兩個方法,所以都需要這此聲明: ~~~ package com.lxj.aidl; import com.lxj.aidl.Book; interface IBookManager { List<Book> getBookList(); void addBook(in Book book); } ~~~ 除了基本數據類型外,其它數據類型都要以in out inout來標識,in表示輸入,out表示輸出,inout即可表示輸入也可表示輸出。 這時系統會自動生成一個IBookManager.java文件,內容如下: ~~~ package com.lxj.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.lxj.aidl.IBookManager { private static final java.lang.String DESCRIPTOR = "com.lxj.aidl.IBookManager"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.lxj.aidl.IBookManager interface, * generating a proxy if needed. */ public static com.lxj.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.lxj.aidl.IBookManager))) { return ((com.lxj.aidl.IBookManager)iin); } return new com.lxj.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<com.lxj.aidl.Book> _result = this.getBookList(); reply.writeNoException(); reply.writeTypedList(_result); return true; } case TRANSACTION_addBook: { data.enforceInterface(DESCRIPTOR); com.lxj.aidl.Book _arg0; if ((0!=data.readInt())) { _arg0 = com.lxj.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.lxj.aidl.IBookManager { 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; } @Override public java.util.List<com.lxj.aidl.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<com.lxj.aidl.Book> _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0); _reply.readException(); _result = _reply.createTypedArrayList(com.lxj.aidl.Book.CREATOR); } finally { _reply.recycle(); _data.recycle(); } return _result; } @Override public void addBook(com.lxj.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); } public java.util.List<com.lxj.aidl.Book> getBookList() throws android.os.RemoteException; public void addBook(com.lxj.aidl.Book book) throws android.os.RemoteException; } ~~~ asInterface:用于將服務端的Binder對象轉換成客戶端所需的AIDL對象,同一進程返回的是服務端的Stub,不同進程返回系統封閉后的Stub.proxy對象。 asBinder:用于返回當前 的Binder對象。 onTransact(code,data,reply,flags):運行在服務端的Binder線程池中,客戶端發出的請求會在此處理。code可以確定客戶端的請求目標方法是什么,data取出參數,運行完把結果賦給reply。如果返回false,則客戶端請求會失敗(可用于權限判斷)。 getBookList:首先創建輸入輸出的Parcel對象_data,_reply。接著調用transact方法來發起RPC(遠程過程調用)請求,同時掛起線程,然后服務端onTransact會調用,直到RPC執行完,當前線程繼續執行,并從_reply取出RPC結果。返回。 ### 四,AIDL進程間調用 aidl是最常見的進程調用方式。我們先創建兩個應用,模擬進程間通信(不同應用)。客戶端的代碼如下: ~~~ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent("com.lxj.servicetest.MyAIDLService"); bindService(intent, connection, Context.BIND_AUTO_CREATE); } private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub IBookManager bookManager = IBookManager.Stub.asInterface(service); try { List<Book> list = bookManager.getBookList(); Log.e("list", list.toString()); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; ~~~ 通過bindService綁定服務端Binder,然后通過IBookManager.Stub.asInterface()來獲得服務端返回的AIDL對象,就可以調用到服務端的方法(getBookList)。再看下服務端代碼: ~~~ public class MyBookService extends Service { private CopyOnWriteArrayList<Book> mBooks = new CopyOnWriteArrayList<Book>(); @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); mBooks.add(new Book(1,"java虛擬機")); mBooks.add(new Book(2,"android瘋狂講義")); } private Binder mBinder = new IBookManager.Stub() { //雖然IBinder只能傳輸List,但是服務端之所以可以用CopyOnWriteArrayList是因為它會自動在傳輸時轉化為list @Override public List<Book> getBookList() throws RemoteException { // TODO Auto-generated method stub return mBooks; } @Override public void addBook(Book book) throws RemoteException { // TODO Auto-generated method stub mBooks.add(book); } }; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return mBinder; } } ~~~ 自定義了一個Service并在list中添加兩本書,所以客戶端就能在控制臺上打印出這兩本書。注意要在AndroidFest.xml添加上Service的聲明: ~~~ <service android:name="com.lxj.aidl.MyBookService" > <intent-filter> <action android:name="com.lxj.servicetest.MyAIDLService"/> </intent-filter> </service> ~~~ ### 五,Messenger進程間通信 android提供Messenger可以實現不同進程間的信息傳遞,相比AIDL它的調用簡單很多,但是它是有缺點的,它只能串行處理發送的信息,如里信息過多就會阻塞。其次它只能傳輸基本數據類型,What,arg1,Bundle等,并不能傳輸自定義的對象。Messenger是一種種輕量級的IPC方案,一次處理一個請求。 1.服務端: 創建一個Service來處理客戶端連接請求,同時創建一個Handler并通過它來創建一個Message對象,然后在OnBinder中返回這個Binder。 2.客戶端: 首先綁定服務端Service,通過返回的IBinder創建一個messager。這個就可以給服務端發消息了,如果需要服務端返回,則也要跟服務端一個創建Handler,通過Message的replyTo參數傳遞給服務端。 先看下客戶端的代碼: 先看客戶端代碼: ~~~ public class MainActivity extends Activity { TextView txvTextView ; private Messenger mService; private Messenger clientMessenger = new Messenger(new MessengerHandler()); private static class MessengerHandler extends Handler{ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch(msg.what){ case 1: Log.e("msg from service", msg.getData().getString("reply")); break; default: super.handleMessage(msg); } } } private ServiceConnection connection = new ServiceConnection(){ @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub mService = new Messenger(service); Message msgMessage = Message.obtain(null,0); Bundle b = new Bundle(); b.putString("client", "Hi,i am client"); msgMessage.setData(b); msgMessage.replyTo = clientMessenger; try { mService.send(msgMessage); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txvTextView = (TextView)super.findViewById(R.id.txv); Intent i = new Intent(this,MessengerService.class); bindService(i, connection, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { unbindService(connection); super.onDestroy(); } } ~~~ 看到上面的代碼我們可以很清楚的看到,Messenger也是用AIDL實現進程間通信的。通過Messenger發送消息到服務端,handler中獲取服務端返回的replyto。再看下服務端代碼: ~~~ public class MessengerService extends Service{ private final Messenger mMessenger = new Messenger(new MessengerHandler()); private static class MessengerHandler extends Handler{ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch(msg.what){ case 0: Log.e("msg from client", msg.getData().getString("client")); Message message = Message.obtain(null,1); Messenger messenger = msg.replyTo;//從客戶端得到的messenger,用于在客戶端中顯示 Bundle bundle = new Bundle(); bundle.putString("reply", "Hi,i am service"); message.setData(bundle); try { Thread.sleep(1000); messenger.send(message); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } break; default: super.handleMessage(msg); } } } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return mMessenger.getBinder(); } } ~~~ 這里就是獲取到信息后再把信息發送回客戶端。完成了不同進程的信息傳遞。 這里只是簡單介紹兩種IPC方式,還有很多常用方式如socket通信,ContentProvider等都可以實現IPC。本文只是總結下自己對IPC的認識。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看