IPC机制的AIDL进阶,结合观察者模式
来源:互联网 发布:js substring 编辑:程序博客网 时间:2024/05/17 23:10
好久没写博客了,最近确实挺忙的,感情也不顺利,一直萎靡着,就这样吧,进入主题了.
在半年前写过篇AIDL的入门Demo,< IPC机制第二篇,AIDL实现> 这边的案例实现是,客户端只有去请求服务器,服务器才会返回结果,那假设有这样一个需求:用户不想时不时地去访问,而是希望当服务器有最新咨询的时候能够主动推送到客户端上来,这就是一种典型的观察者模式了,当然里面还有一些问题需要注意的我们等下来总结.
1 . IOnNewBookArrivedListener.aidl
// IOnNewBookArrivedListener.aidlpackage com.tom.aidldemo;// Declare any non-default types here with import statementsimport com.tom.aidldemo.Book;interface IOnNewBookArrivedListener { void onNewBookArrived(in Book book);}
2 . IBookManager.aidl
// IBookManager.aidlpackage com.tom.aidldemo;// Declare any non-default types here with import statementsimport com.tom.aidldemo.Book;import com.tom.aidldemo.IOnNewBookArrivedListener;interface IBookManager { List<Book> getBookList(); void addBook(in Book book); void registerListener(IOnNewBookArrivedListener listener); void unregisterListener(IOnNewBookArrivedListener listener);}
3 . Book.java
public class Book implements Parcelable { public int bookId; public String bookName; public Book(int bookId, String bookName) { this.bookId = bookId; this.bookName = bookName; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(this.bookId); dest.writeString(this.bookName); } public Book() { } protected Book(Parcel in) { this.bookId = in.readInt(); this.bookName = in.readString(); } 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]; } };}
4 . Book.aidl
// Book.aidl.aidlpackage com.tom.aidldemo;// Declare any non-default types here with import statementsparcelable Book;
5 . 服务器代码BookManagerService.java
public class BookManagerService extends Service { private static final String TAG = "BookManagerService"; private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<Book>(); private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);// private CopyOnWriteArrayList<IOnNewBookArrivedListener> mListenerList =// new CopyOnWriteArrayList<IOnNewBookArrivedListener>(); private RemoteCallbackList<IOnNewBookArrivedListener> mListenerList = new RemoteCallbackList<IOnNewBookArrivedListener>(); public BookManagerService() { } 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); } @Override public void unregisterListener(IOnNewBookArrivedListener listener) throws RemoteException { mListenerList.unregister(listener); } }; @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() { mIsServiceDestoryed.set(true); super.onDestroy(); } @Override public IBinder onBind(Intent intent) { return mBinder; } private class ServiceWorker implements Runnable { @Override public void run() { while (!mIsServiceDestoryed.get()){ try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } int bookId = mBookList.size() + 1; Book newBook = new Book(bookId, "new book#" + bookId); try { onNewBookArray(newBook); } catch (RemoteException e) { e.printStackTrace(); } } } } private void onNewBookArray(Book newBook) throws RemoteException { mBookList.add(newBook); int N = mListenerList.beginBroadcast(); for (int i = 0; i<N; i++){ IOnNewBookArrivedListener broadcastItem = mListenerList.getBroadcastItem(i); if(broadcastItem != null) { broadcastItem.onNewBookArrived(newBook); } } mListenerList.finishBroadcast(); }}
6 . 客户端代码MainActivity.java
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private static final int MESSAGE_NEW_BOOK_ARRIVED = 1; private IBookManager mRemoteBookManager; private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { switch(msg.what){ case MESSAGE_NEW_BOOK_ARRIVED: Log.d(TAG, "收到新书: " + msg.obj); break; default: super.handleMessage(msg); break; } } }; private ServiceConnection mConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { IBookManager bookManager = IBookManager.Stub.asInterface(service); try { mRemoteBookManager = bookManager; List<Book> bookList = bookManager.getBookList(); Log.i(TAG, "query book list, list type: " + bookList.getClass().getCanonicalName()); Log.i(TAG, "query book list: " + bookList.toString()); Book newBook = new Book(3, "数学之美"); bookManager.addBook(newBook); Log.i(TAG, "onServiceConnected: " + newBook); bookList = bookManager.getBookList(); Log.i(TAG, "query book list, list type: " + bookList.getClass().getCanonicalName()); Log.i(TAG, "query book list: " + bookList.toString()); bookManager.registerListener(mOnNewBookArrivedListener); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { mRemoteBookManager = null; Intent intent = new Intent(MainActivity.this, BookManagerService.class); bindService(intent, mConn, Context.BIND_AUTO_CREATE); } }; private IOnNewBookArrivedListener mOnNewBookArrivedListener = new IOnNewBookArrivedListener.Stub() { @Override public void onNewBookArrived(Book book) throws RemoteException { mHandler.obtainMessage(MESSAGE_NEW_BOOK_ARRIVED, book).sendToTarget(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent(this, BookManagerService.class); bindService(intent, mConn, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { if(mRemoteBookManager != null && mRemoteBookManager.asBinder().isBinderAlive()){ try { mRemoteBookManager.unregisterListener(mOnNewBookArrivedListener); } catch (RemoteException e) { e.printStackTrace(); } } unbindService(mConn); super.onDestroy(); }}
AIDL难点理解:
1 . AIDL底层是通过Binder实现的,但是Binder会把客户端传来的对象重新转化并生成一个新的对象.虽然我们在观察者模式注册和解注册的时候使用的是同一个对象,但是通过Binder传递到服务器之后会产生两个对象.因为对象是不能够跨进程传输的,实际的传输是Binder的序列化和反序列化的过程,但是两次的序列化操作Binder是同一个.
解决方案使用RemoteCallbackList.
2 . 不管是客户端还是服务器,我们都可以看到每个方法都会抛一个异常RemoteException.为什么?因为进程间的通信,不管是服务端也好还是客户端也好跨进程的方法都是在Binder线程池中的运行的,也就是说是非UI线程.所以切记耗时不能运行在主线程中,不然就会报ANR了.
3 . Binder是会意外死亡的,所以我们要在onServiceDisconnected中进行重连远程服务
4 . 客户端和服务端的权限验证,这个请读者自行百度,主要是在服务端的onBind方法是否返回null来控制.
- IPC机制的AIDL进阶,结合观察者模式
- Android IPC机制之AIDL的使用
- IPC机制分析和AIDL的使用
- Android AIDL IPC机制
- IPC机制---使用AIDL
- IPC机制<二>AIDL
- IPC机制(AIDL)
- Android AIDL IPC机制详解
- IPC机制之AIDL、Messenger
- Android IPC机制-AIDL详解
- android IPC机制之 AIDL
- 进阶式IPC机制
- Android中RemoteService的使用详解(Aidl、IPC机制)
- Android IPC机制(二):AIDL的基本使用方法
- 简单理解IPC机制和AIDL的使用
- 观察者模式和Spring的结合
- Android进阶:AIDL实现IPC使用详解
- 【Android机制】IPC机制之AIDL
- POJ 2253 Frogger(Dijkstra变形)
- 今天开始找工作了
- Python常用框架及第三方库
- win10小娜助手无法搜索本地应用怎么办
- 深入理解Java并发4——synchronized关键字
- IPC机制的AIDL进阶,结合观察者模式
- 文章标题
- 开源一个Android视频播放器项目ZhVideoPlayer
- Hadoop面试题 (网上收集版带答案)
- 面向对象基本先关概念
- Floyed-Warshall-求最短路
- HTML5 aside元素
- leetCode练习(187)
- NSWindow支持Drag-and-Drop