IPC机制之AIDL实现客户端回调
来源:互联网 发布:软件测试各个阶段 编辑:程序博客网 时间:2024/06/05 12:49
IPC机制之AIDL传递基础类型数据
IPC机制之AIDL传递Parcelable
IPC机制之Messenger示例
序言
前面的3篇文章文章实现了多进程的通讯,但是都只完成了客户端调用服务端的方法或者客户端发送消息和服务端通信,下面我们介绍下AIDL中的观察者模式,客户端绑定服务端成功狗,回调客户端的方法。
以上代码都在在 IPC机制之AIDL传递Parcelable 文章的基础上实现的,所以只展示不同代码,后面会附上完整代码。
Server#IOnNewBookArrivedListener.aidl
package com.aidd.sample;import com.aidd.sample.Book;interface IOnNewBookArrivedListener { void onNewBookArrived(in Book newBook);}
Server#IBookManager.aidl
package com.aidd.sample;import com.aidd.sample.Book;import com.aidd.sample.IOnNewBookArrivedListener;interface IBookManager { List<Book> getBookList(); void addBook(in Book book); void registerListener(IOnNewBookArrivedListener listener); void unregisterListener(IOnNewBookArrivedListener listener);}
Server#BookManagerService.java
package com.aidd.sample;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.os.RemoteCallbackList;import android.os.RemoteException;import android.support.annotation.Nullable;import android.util.Log;import java.util.List;import java.util.concurrent.CopyOnWriteArrayList;import java.util.concurrent.atomic.AtomicBoolean;public class BookManagerService extends Service { private AtomicBoolean mIsServiceDestroyed = new AtomicBoolean(false); private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>(); private RemoteCallbackList<IOnNewBookArrivedListener> mListenerList = new RemoteCallbackList<>(); private String TAG = "info"; @Override public void onCreate() { super.onCreate(); mBookList.add(new Book(1, "Android")); mBookList.add(new Book(2, "iOS")); new Thread(new ServiceWorker()).start(); } @Override public void onDestroy() { mIsServiceDestroyed.set(true); super.onDestroy(); } private Binder mBinder = new IBookManager.Stub() { @Override public List<Book> getBookList() throws RemoteException { return mBookList; } @Override public void addBook(Book book) throws RemoteException { mBookList.add(book); } @Override public void registerListener(IOnNewBookArrivedListener listener) throws RemoteException { mListenerList.register(listener); int count = mListenerList.beginBroadcast(); Log.i(TAG, "registerListener success, count-->>" + count); mListenerList.finishBroadcast(); } @Override public void unregisterListener(IOnNewBookArrivedListener listener) throws RemoteException { mListenerList.unregister(listener); int count = mListenerList.beginBroadcast(); Log.i(TAG, "unregisterListener success, count-->>" + count); mListenerList.finishBroadcast(); } }; @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } private void onNewBookArrived(Book book) throws RemoteException { mBookList.add(book); final int N = mListenerList.beginBroadcast(); Log.i(TAG, "onNewBookArrived, notify booklist-->>" + mBookList.size()); for (int i = 0; i < N; i++) { IOnNewBookArrivedListener arrivedListener = mListenerList.getBroadcastItem(i); if (arrivedListener != null) arrivedListener.onNewBookArrived(book); } mListenerList.finishBroadcast(); } private class ServiceWorker implements Runnable { @Override public void run() { while (!mIsServiceDestroyed.get()) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } int bookId = mBookList.size() + 1; Book newBook = new Book(bookId, "new book#" + bookId); try { onNewBookArrived(newBook); } catch (RemoteException e) { e.printStackTrace(); } } } }}
RemoteCallbackList 是一个键值对,Key是Binder,value就是回调的callback,目的是为了记录注册了回调的客户端。
Client#MainActivity.java
package sample.aidl.com.client;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.os.RemoteException;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import com.aidd.sample.Book;import com.aidd.sample.IBookManager;import com.aidd.sample.IOnNewBookArrivedListener;import java.util.List;public class MainActivity extends AppCompatActivity { private IBookManager iBookManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void startIPC(View view) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.aidd.sample", "com.aidd.sample.BookManagerService")); this.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { iBookManager = IBookManager.Stub.asInterface(service); try { List<Book> bookList = iBookManager.getBookList(); Log.i("info", "列表类型" + bookList.getClass().getCanonicalName()); Log.i("info", "数据查询结果" + bookList.toString()); iBookManager.registerListener(mListener); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { iBookManager = null; } }; Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: Log.i("info", "recive new book"); break; } } }; private IOnNewBookArrivedListener mListener = new IOnNewBookArrivedListener.Stub() { @Override public void onNewBookArrived(Book newBook) throws RemoteException { handler.obtainMessage(1, newBook).sendToTarget(); } }; @Override protected void onDestroy() { if (iBookManager != null && iBookManager.asBinder().isBinderAlive()) { try { iBookManager.unregisterListener(mListener); } catch (RemoteException e) { e.printStackTrace(); } } unbindService(mConnection); super.onDestroy(); }}
Q: Client#MainActivity.java中为什么IOnNewBookArrivedListener回调方法使用Handle?
A: 因为客户端的回调方法运行在客户端的Binder线程池中,即子线程,所以无法直接更新UI,但是onServiceConnected和onServiceDisconnected是运行在UI线程的。
Q: Server#BookManagerService.java中的mBinder方法是运行在哪里?
A: 客户端调用服务端的方法也是运行在Binder线程池中的,只是是运行在服务端的Binder线程池中,所以这里面的方法是非UI线程中。
Q: 服务端binder提供的方法是不是可以执行耗时操作?
A: 由于Binder中的方法是在Binder线程池中,所以是可以执行耗时操作的,但是如果客户端是在UI线程中调用的这些方法,会导致客户端长时间收不到回调而卡死,出现ANR。同理,如果服务端如果在主线程中调用客户端的回调方法时,如果是客户端回调是耗时操作,服务端也会出现ANR。
源码下载
- IPC机制之AIDL实现客户端回调
- IPC机制之AIDL、Messenger
- android IPC机制之 AIDL
- 【Android机制】IPC机制之AIDL
- IPC之AIDL(1)实现AIDL
- 在Android使用AIDL实现IPC机制
- IPC机制第二篇,AIDL实现
- Android IPC机制之AIDL的使用
- IPC机制之AIDL传递Parcelable
- 使用AIDL实现IPC通信之——实现服务端主动发送数据给客户端
- IPC机制之四:IPC方式(AIDL)
- Android AIDL IPC机制
- IPC机制---使用AIDL
- IPC机制<二>AIDL
- IPC机制(AIDL)
- 使用AIDL实现IPC
- Android中IPC(进程间通信)机制之AIDL
- Android IPC 进程间通信机制之 AIDL
- PHP foreach循环
- java发送邮箱
- Shell脚本函数定义和函数参数
- 把二元查找树转变成排序的双向链表
- Struts2的数据验证框架validation framework
- IPC机制之AIDL实现客户端回调
- struts2编写自定义的验证程序
- python 3.5配置opencv
- Web Uploader的JS代码(一)
- 23day JSON/XML
- 指针和引用的区别
- 成为一名优秀程序员所需要知道的那些事
- kmp算法
- VBO, PBO与FBO(一)