首先进程间通讯的方式有:广播,ContentProvider(内容提供者),AIDL(Android接口定义语言)
今天我们所讲的就是AIDL:
首先定义AIDL接口文件,如果进程间要传递对象,那么这个对象必须实现Praceable接口:

// Book.aidl
package com.example.aidl;parcelable Book;

远程服务端的方法,当图书变化的时候通知给监听者

package com.example.aidl;import com.example.aidl.Book;
import com.example.aidl.IOnNewBookArriverdListener;interface IBookManager {List<Book> getBookList();void addBock(in Book book);void registerListener(IOnNewBookArriverdListener listener);void unregisterListener(IOnNewBookArriverdListener listener);
}

监听器接口

package com.example.aidl;import com.example.aidl.Book;interface IOnNewBookArriverdListener {void onNewBookArrived(in Book newBook);
}

Book类,注意:Book类所在的包名

package com.example.aidl;import android.os.Parcel;
import android.os.Parcelable;public class Book implements Parcelable {private int no = 0;private String name;public Book(int no, String name) {this.no = no;this.name = name;}protected Book(Parcel in) {no = in.readInt();name = in.readString();}public static final Creator<Book> CREATOR = new Creator<Book>() {@Overridepublic Book createFromParcel(Parcel in) {return new Book(in);}@Overridepublic Book[] newArray(int size) {return new Book[size];}};public int getNo() {return no;}public void setNo(int no) {this.no = no;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeInt(no);dest.writeString(name);}@Overridepublic String toString() {return "Book{" +"no=" + no +", name='" + name + '\'' +'}';}
}

服务端需要注意的是:存储监听器的类是RemoteCallbackList

package com.example.service;import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;import com.example.aidl.Book;
import com.example.aidl.IBookManager;
import com.example.aidl.IOnNewBookArriverdListener;import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;public class BookManagerService extends Service {private static final String TAG = "BookManagerService";private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();
//    这种写法,当解绑服务的时候,服务端竟然无法找到我们之前注册的那个listener,在客户端我们注册和解注册的时候
//    明明传递的是同一个 Listener啊!,最终服务端无法找到要解除的listener,而宣告失败,这当然不是我们想要的结果.
//    因为Binder会把客户端传递过来的对象重新转化并生成一个新的对象,虽然我们注册和解注册的过程传递的是同一个对象
//    但是,通过Binder传递到服务端之后,却会产生两个全新的对象,别忘了对象是不能跨进程传递的,对象的跨进程传递本质上
//    反序列化的过程,这就是为什么AIDL中的自定义对象都必须要实现Parcelable接口的原因,
//    那么我们如何才能实现解注册的功能呢?答案是 RemoteCallbackList,//        private CopyOnWriteArrayList<IOnNewBookArriverdListener> mListenerList = new CopyOnWriteArrayList<>();private RemoteCallbackList<IOnNewBookArriverdListener> mListenerList = new RemoteCallbackList<>();public BookManagerService() {}private void onNewBookArrived(Book book) throws RemoteException {mBookList.add(book);System.out.println("lgj service mBookList size:" + mBookList.size());
//        for (int i = 0; i < mListenerList.size(); i++) {
//            IOnNewBookArriverdListener listener = mListenerList.get(i);
//            listener.onNewBookArrived(book);
//        }int N = mListenerList.beginBroadcast();for (int i = 0; i < N; i++) {IOnNewBookArriverdListener broadcastItem = mListenerList.getBroadcastItem(i);if (broadcastItem != null) {broadcastItem.onNewBookArrived(book);}}mListenerList.finishBroadcast();}private Binder mBinder = new IBookManager.Stub() {@Overridepublic List<Book> getBookList() throws RemoteException {System.out.println("lgj service Binder pid:" + android.os.Process.myPid() + " tid:" + Process.myTid());return mBookList;}@Overridepublic void addBock(Book book) throws RemoteException {mBookList.add(book);}@Overridepublic void registerListener(IOnNewBookArriverdListener listener) throws RemoteException {
//            if (!mListenerList.contains(listener)){
//                mListenerList.add(listener);
//            }else {
//                System.out.println(TAG + "lgj already exists...");
//            }
//            System.out.println(TAG + "lgj service register listener size :" +mListenerList.size() );mListenerList.register(listener);System.out.println(TAG + "lgj service register listener size :" + mListenerList.getRegisteredCallbackCount());}@Overridepublic void unregisterListener(IOnNewBookArriverdListener listener) throws RemoteException {
//            if (mListenerList.contains(listener)){
//                mListenerList.remove(listener);
//            }else {
//                System.out.println(TAG + "lgj service not found,can not unregister...");
//            }
//            System.out.println(TAG + "lgj service unregister listener size :" +mListenerList.size());mListenerList.unregister(listener);System.out.println(TAG + "lgj service unregister listener size :" + mListenerList.getRegisteredCallbackCount());}};@Overridepublic IBinder onBind(Intent intent) {return mBinder;}@Overridepublic void onDestroy() {super.onDestroy();System.out.println("lgj service BookManagerService onDestroy...");mIsServiceDestoryed.set(true);}private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);@Overridepublic void onCreate() {super.onCreate();// 模拟每隔5秒钟图书发生变化new Thread(new Runnable() {@Overridepublic void run() {while (!mIsServiceDestoryed.get()) {try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}int bookId = mBookList.size() + 1;Book book = new Book(bookId, "new book#" + bookId);try {onNewBookArrived(book);} catch (RemoteException e) {e.printStackTrace();}}}}).start();}
}

客户端代码:

        Intent intent = new Intent(this, BookManagerService.class);
//        startService(intent); 长期运行在后台,
//        如果只是简单的bind没有start的话,那么退出Activity 服务也会随之而停止,
//        我理解Activity绑定服务的话,随着Activity的存在即服务而存在,随着Activity的销毁服务则停止
//        (即使你在Activity的onDestroy方法中没有调用unbindService() 这个方法,服务也会停止)bindService(intent,connection, Context.BIND_AUTO_CREATE);
     private IOnNewBookArriverdListener mListener = new IOnNewBookArriverdListener.Stub() {@Overridepublic void onNewBookArrived(Book newBook) throws RemoteException {System.out.println("lgj xinshu : " + newBook.getName());}};public IBookManager mBookManager;ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mBookManager = IBookManager.Stub.asInterface(service);if (mBookManager != null){try {//添加注册监听实例对象mBookManager.registerListener(mListener);} catch (RemoteException e) {e.printStackTrace();}}}@Overridepublic void onServiceDisconnected(ComponentName name) {}};

注意ondestroy记得取消注册监听

    @Overrideprotected void onDestroy() {try {mBookManager.unregisterListener(mListener);} catch (RemoteException e) {e.printStackTrace();}
//        unbindService(connection);super.onDestroy();}

进程间通讯回调客户端相关推荐

  1. Android-Binder进程间通讯机制-多图详解

    本系列: Android-Binder进程间通讯机制-多图详解 一次Binder通信最大可以传输多大的数据?​​​​​​​ 关于Binder (AIDL)的 oneway 机制 概述 最近在学习Bin ...

  2. linux open 头文件_linux下通过共享内存和mmap实现进程间通讯

    前言 最近在学习GNU/Linux内核,看到mmap的时候书上说: mmap/munmap接口函数是用户最常用的两个系统调用接口,无论是在用户程序中分配内存.读写大文件.链接动态库文件,还是多进程间共 ...

  3. Android(IPC)进程间通讯1:详解Binder由来?

    完整原文:http://tryenough.com/android-... Android开发的进程间通讯,整个Android的应用都依赖于binder做底层通信机制.而Linux中提供的进程间通讯方 ...

  4. linux mmap实例_Linux下通过共享内存和mmap实现进程间通讯(含实例)

    前言 最近在学习GNU/Linux内核,看到mmap的时候书上说: mmap/munmap接口函数是用户最常用的两个系统调用接口,无论是在用户程序中分配内存.读写大文件.链接动态库文件,还是多进程间共 ...

  5. Python 第八篇:异常处理、Socket语法、SocketServer实现多并发、进程和线程、线程锁、GIL、Event、信号量、进程间通讯...

    本节内容: 异常处理.Socket语法.SocketServer实现多并发.进程和线程.线程锁.GIL.Event.信号量.进程间通讯.生产者消费者模型.队列Queue.multiprocess实例 ...

  6. WIN32 进程间通讯-共享内存

    一.引言     在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯.WIN32 API提供了许多函数使我们能够方便高效的进行进程间的通讯,通过这些函数我们可以控制不同进程间的数据交换 ...

  7. 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制

    概述 最近在学习Binder机制,在网上查阅了大量的资料,也看了老罗的Binder系列的博客和Innost的深入理解Binder系列的博客,都是从底层开始讲的,全是C代码,虽然之前学过C和C++,然而 ...

  8. 【Linux】-- 进程间通讯

    目录 进程间通讯概念的引入 意义(手段) 思维构建 进程间通信方式 管道 站在用户角度-浅度理解管道 匿名管道 pipe函数 站在文件描述符角度-深度理解管道 管道的特点总结 管道的拓展 单机版的负载 ...

  9. Android查缺补漏(IPC篇)-- 进程间通讯之Socket简介及示例

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8425736.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

最新文章

  1. 2022-2028年中国塑料人造革行业市场研究及前瞻分析报告
  2. 掌握管理Linux磁盘和分区的方法 创建并挂载文件系统以及 创建并管理LVM
  3. JavaScript 输出
  4. Mac IntelliJ IDEA 快捷键终极大全,速度收藏!
  5. Linux kmap和kmap_atomic解析
  6. ubuntu环境下,ubuntu16.04装机到nvdia显卡驱动安装、cuda8安装、cudnn安装
  7. mysql 镜像安装方法_MySql镜像安装
  8. 叶三《我们唱》-野孩子(白银饭店)
  9. 一文详解双目立体匹配算法:ELAS
  10. 使用计算机有关的活动,与计算机有关的传统文化活动策划书
  11. C++ strcpy strcpy_s strncpy strlcpy
  12. POI使用word模板文件循环输出行并导出word
  13. 警猫眼Arduino源码分享,把闲置手机变成安防监控摄像头!
  14. Unity Animator 动画没切换
  15. 如何爬取新三板数据(二)
  16. c语言求三门课程的平均成绩,C语言求三个学生四门课每个学生的平均成绩和每门课的平均成绩,并存入cx.txt中...
  17. Python编程:socket实现文件传输(文件服务器简易版)
  18. 基于Matlab的脑功能网络工具箱 BCT FCLab
  19. php密码探测软件,Radmin密码读取工具(php版)
  20. 教你如何开发VR游戏系列教程一:前言

热门文章

  1. c语言哈夫曼树统计字母频率,C语言实现哈夫曼树
  2. c++第十天(隐藏与覆盖)(面试常问)
  3. Qtcreator中使用角蜂鸟相机
  4. 【翻译】 A survey of transfer learning迁移学习综述
  5. 房产管理系统---系统安全性需求分析
  6. 2020年生态红线调整技术方案----解读
  7. 强悍双芯热血酷玩 iQOO Neo5S手机发布
  8. Electron-vue第一章:创建和自动生成嵌套路由
  9. The path to the driver executable must be set by the webdriver.edge.driver system property
  10. 如何ETH以太坊智能合约做一个简单的DAPP