当前位置: 首页 > news >正文

Android 多进程开发 - 服务端死亡回调、服务端与客户端的线程环境、oneway 关键字

一、服务端死亡回调

  • 在绑定服务端时,可以获取服务端时的 Binder 对象,调用 Binder 对象的 linkToDeath 方法,注册死亡回调,监听服务端时是否挂了
privateIMyAidlInterfacemyAidlInterface;privatebooleanisBound=false;privatefinalIBinder.DeathRecipientdeathRecipient=newIBinder.DeathRecipient(){@OverridepublicvoidbinderDied(){Log.i(TAG,"检测到服务端进程死亡");}};privateServiceConnectionconnection=newServiceConnection(){@OverridepublicvoidonServiceConnected(ComponentNamename,IBinderservice){Log.i(TAG,"服务连接成功");myAidlInterface=IMyAidlInterface.Stub.asInterface(service);try{service.linkToDeath(deathRecipient,0);}catch(RemoteExceptione){e.printStackTrace();}isBound=true;}@OverridepublicvoidonServiceDisconnected(ComponentNamename){Log.i(TAG,"服务连接断开");myAidlInterface=null;isBound=false;// 系统会处理 unlinkToDeath、unbindService}};
  • 触发 onServiceDisconnected 回调,系统会处理 unlinkToDeath、unbindService,不需要手动调用,详见源码
// 1. doDeath 方法源码publicvoiddoDeath(ComponentNamename,IBinderservice){synchronized(this){ConnectionInfoold=mActiveConnections.get(name);if(old==null||old.binder!=service){// Death for someone different than who we last// reported... just ignore it.return;}mActiveConnections.remove(name);old.binder.unlinkToDeath(old.deathMonitor,0);}mConnection.onServiceDisconnected(name);}
// doDeath 方法中的清理逻辑mActiveConnections.remove(name);old.binder.unlinkToDeath(old.deathMonitor,0);
// 2. doConnected 方法publicvoiddoConnected(ComponentNamename,IBinderservice,booleandead){ServiceDispatcher.ConnectionInfoold;ServiceDispatcher.ConnectionInfoinfo;synchronized(this){if(mForgotten){// We unbound before receiving the connection; ignore// any connection received.return;}old=mActiveConnections.get(name);if(old!=null&&old.binder==service){// Huh, already have this one. Oh well!return;}if(service!=null){// A new service is being connected... set it all up.info=newConnectionInfo();info.binder=service;info.deathMonitor=newDeathMonitor(name,service);try{service.linkToDeath(info.deathMonitor,0);mActiveConnections.put(name,info);}catch(RemoteExceptione){// This service was dead before we got it... just// don't do anything with it.mActiveConnections.remove(name);return;}}else{// The named service is being disconnected... clean up.mActiveConnections.remove(name);}if(old!=null){old.binder.unlinkToDeath(old.deathMonitor,0);}}// If there was an old service, it is now disconnected.if(old!=null){mConnection.onServiceDisconnected(name);}if(dead){mConnection.onBindingDied(name);}else{// If there is a new viable service, it is now connected.if(service!=null){mConnection.onServiceConnected(name,service);}else{// The binding machinery worked, but the remote returned null from onBind().mConnection.onNullBinding(name);}}}
// doConnected 方法中的清理逻辑if(old!=null){old.binder.unlinkToDeath(old.deathMonitor,0);}

二、服务端与客户端的线程环境

1、服务端
  1. AIDL 接口,在主线程执行(无论客户端是在主线程调用,还是在子线程调用)
privatefinalIMyAidlInterface.Stubbinder=newIMyAidlInterface.Stub(){@Overridepublicintadd(inta,intb)throwsRemoteException{// Binder 线程returna+b;}}
  1. DeathRecipient 回调,在 Binder 线程执行
IBinder.DeathRecipientdr=newDeathRecipient(){@OverridepublicvoidbinderDied(){// Binder 线程}};
2、客户端
  1. ServiceConnection 回调,在主线程执行
privateServiceConnectionconnection=newServiceConnection(){@OverridepublicvoidonServiceConnected(ComponentNamename,IBinderservice){// 主线程}@OverridepublicvoidonServiceDisconnected(ComponentNamename){// 主线程}};
  1. DeathRecipient 回调,在 Binder 线程执行
privatefinalIBinder.DeathRecipientdeathRecipient=newIBinder.DeathRecipient(){@OverridepublicvoidbinderDied(){// 主线程}};
  1. AIDL 接口调用,调用前后都是在调用者线程执行
try{// 主线程intresult=myAidlInterface.add(5,3);Log.i(TAG,"add result: "+result);// 主线程}catch(RemoteExceptione){e.printStackTrace();Log.e(TAG,"add method error: "+e.getMessage());}
newThread(()->{try{// 子线程intresult=myAidlInterface.add(5,3);Log.i(TAG,"add result: "+result);// 子线程}catch(RemoteExceptione){e.printStackTrace();Log.e(TAG,"add method error: "+e.getMessage());}}).start();
  1. AIDL 接口回调,在主线程执行(无论客户端是在主线程注册,还是在子线程注册)
callback=newIPlayerCallback.Stub(){@OverridepublicvoidonSongChanged(StringsongName)throwsRemoteException{// 主线程Log.i(TAG,"onSongChanged: "+songName);}@OverridepublicvoidonPlayStateChanged(booleanisPlaying)throwsRemoteException{// 主线程Log.i(TAG,"onPlayStateChanged: "+isPlaying);}};try{myAidlInterface.registerCallback(callback);Log.i(TAG,"registerCallback method success");}catch(RemoteExceptione){e.printStackTrace();Log.e(TAG,"registerCallback method error: "+e.getMessage());}
newThread(()->{callback=newIPlayerCallback.Stub(){@OverridepublicvoidonSongChanged(StringsongName)throwsRemoteException{// 主线程Log.i(TAG,"onSongChanged: "+songName);}@OverridepublicvoidonPlayStateChanged(booleanisPlaying)throwsRemoteException{// 主线程Log.i(TAG,"onPlayStateChanged: "+isPlaying);}};try{myAidlInterface.registerCallback(callback);Log.i(TAG,"registerCallback method success");}catch(RemoteExceptione){e.printStackTrace();Log.e(TAG,"registerCallback method error: "+e.getMessage());}}).start();

三、oneway 关键字

1、基本介绍
  • oneway 关键字修饰的方法,客户端调用后立即返回,不等待服务端执行完成
onewayvoiddoSomething();
2、注意事项
  1. oneway 方法不能有返回值,否则编译报错
onewayStringdoSomething();
# 输出结果 oneway method 'doSomething' cannot return a value
  1. oneway 方法的参数可以用 in 修饰
onewayvoiddoSomething(inbyte[]data);
  1. oneway 方法的参数不能用 out 或 inout 修饰,否则编译报错
onewayvoiddoSomething(outbyte[]data);
# 输出结果 oneway method 'doSomething' cannot have out parameters
onewayvoiddoSomething(inoutbyte[]data);
# 输出结果 oneway method 'doSomething' cannot have out parameters
http://www.jsqmd.com/news/438020/

相关文章:

  • 手把手教你本地部署ChatGLM-6B大模型,告别环境配置烦恼!保姆级教程速看!
  • 意义哲学与空
  • Vue - Vue2 与 Vue3 自定义插件
  • Qwen3.5重磅登场!阿里开源“原生多模态”AI核弹,能否引爆2026技术革命?
  • Win系统下Ollama大模型安装与Chatbox部署全攻略,手把手教你玩转AI!
  • 一台电脑控制N台手机实现投屏群控操作,搭建引流工作室必备技能
  • 2026桔多多平台怎么样?服务体验与使用指南详解 - 品牌排行榜
  • PicoServer 跨平台 Web 架构实战系列 (一) MAUI 中嵌入 PicoServer 入门
  • 2026马赛克瓷砖品牌排行有哪些?实力品牌推荐 - 品牌排行榜
  • 2026年马赛克瓷砖厨房用哪种好?推荐品牌参考 - 品牌排行榜
  • tiktok 网页端算法分析
  • 2026年机票比价后在哪个渠道下单更有保障? - 品牌排行榜
  • 2026马赛克瓷砖十大品牌推荐:品质与设计的匠心之选 - 品牌排行榜
  • 2026哪个平台买机票便宜?实用购票攻略及平台推荐 - 品牌排行榜
  • 2026哪个平台有特价机票?实用功能助你轻松省钱 - 品牌排行榜
  • 2026哪个平台有直飞优惠?高性价比出行选择参考 - 品牌排行榜
  • 2026年做澄清过滤的靠谱公司有哪些 - 品牌排行榜
  • Jamf Cloud证书配置全解析
  • 100个AI术语表:从核心概念到前沿技术,这份指南助你快速上手大模型时代!
  • 2026年AI大模型常问的问题以及答案,最新的面试大厂题!
  • 基于Django的大语言模型服务端实现与实战应用
  • 26年大模型面试必问八股文,背完通过率98%,看我如何吊打面试官
  • 告别幻觉与黑箱!LOM本体大模型如何引领企业决策智能化革命?
  • 深入解析 OpenAI API 客户端:超越基础调用的高级实践与架构设计
  • VLLM本地部署大模型保姆级教程:从环境搭建到RAGFlow集成,数据安全又高效!
  • AI工具大比拼:Coze、Dify、n8n、LangChain,哪个才是你的“AI神器”?
  • 保姆级教程:vLLM部署Qwen2-7B大模型,新手半小时轻松搞定,本地运行更香!
  • 大模型面试实录:20家公司Offer与拒信背后,我悟出了这些职场真相!
  • 自动上下料机械手定制哪家专业?2026年优质冲压机械手生产商与靠谱冲床机械手厂家实力推荐:无锡岩回自动化领衔 - 栗子测评
  • OpenSpec新手教程-20260304