作者:手机用户2602918323 | 来源:互联网 | 2023-09-13 09:36
微信移动开发团队在《Android内存优化杂谈》一文中就说到:“对于webview,图库等,由于存在内存系统泄露或者占用内存过多的问题,我们可以采用单独的进程。微信当前也会把它们放
目录
- 前言
- 为什么要使用多进程?
- 为什么需要“跨进程通讯”?
- 跨进程通讯的方式有哪些?
- 使用AIDL实现一个多进程消息推送
- 实现思路
- 例子具体实现
- 知其然,知其所以然。
- 跨进程的回调接口
- DeathRecipient
- 权限验证
- 根据不同进程,做不同的初始化工作
- 总结
- 结语
为什么要使用多进程
- 对于进程的概念,来到这里的都是编程修仙之人,就不再啰嗦了,相信大家倒着、跳着、躺着、各种姿势都能背出来。
- 相信很多同学在实际开发中,基本都不会去给app划分进程,而且,在Android中使用多进程,还可能需要编写额外的进程通讯代码,还可能带来额外的Bug,这无疑加大了开发的工作量,在很多创业公司中工期也不允许,这导致了整个app都在一个进程中。
整个app都在一个进程有什么弊端?
- 在Android中,虚拟机分配给各个进程的运行内存是有限制值的(这个值可以是32M,48M,64M等,根据机型而定),试想一下,如果在app中,增加了一个很常用的图片选择模块用于上传图片或者头像,加载大量Bitmap会使app的内存占用迅速增加,如果你还把查看过的图片缓存在了内存中,那么OOM的风险将会大大增加,如果此时还需要使用WebView加载一波网页,我就问你怕不怕!
微信,微博等主流app是如何解决这些问题的?
- 微信移动开发团队在 《Android内存优化杂谈》 一文中就说到:“对于webview,图库等,由于存在内存系统泄露或者占用内存过多的问题,我们可以采用单独的进程。微信当前也会把它们放在单独的tools进程中”。
下面我们使用adb查看一下微信和微博的进程信息(Android 5.0以下版本可直接在“设置 -> 应用程序”相关条目中查看):

不知道你有没有感觉到,两个进程交互总是觉得缺乏那么一点安全感…比如说服务端进程Crash了,而客户端进程想要调用服务端方法,这样就调用不到了。此时我们可以给Binder设置一个DeathRecipient对象,当Binder意外挂了的时候,我们可以在DeathRecipient接口的回调方法中收到通知,并作出相应的操作,比如重连服务等等。
DeathRecipient的使用如下:
- 声明DeathRecipient对象,实现其binderDied方法,当binder死亡时,会回调binderDied方法;
- 给Binder对象设置DeathRecipient对象。
在客户端MainActivity声明DeathRecipient:

Binder中两个重要方法:
- linkToDeath -> 设置死亡代理 DeathRecipient 对象;
- unlinkToDeath -> Binder死亡的情况下,解除该代理。
此外,Binder中的isBinderAlive也可以判断Binder是否死亡
权限验证
就算是公交车,上车也得嘀卡对不,如果希望我们的服务进程不想像公交车一样谁想上就上,那么我们可以加入权限验证。
介绍两种常用验证方法:
- 在服务端的onBind中校验自定义permission,如果通过了我们的校验,正常返回Binder对象,校验不通过返回null,返回null的情况下客户端无法绑定到我们的服务;
- 在服务端的onTransact方法校验客户端包名,不通过校验直接return false,校验通过执行正常的流程。
自定义permission,在Androidmanifest.xml中增加自定义的权限:

服务端检查权限的方法:


根据不同进程,做不同的初始化工作
相信前一两年很多朋友还在使用Android-Universal-Image-Loader来加载图片,它是需要在Application类进行初始化的。打个比如,我们用它来加载图片,而且还有一个图片选择进程,那么我们希望分配更多的缓存给图片选择进程,又或者是一些其他的初始化工作,不需要在图片选择进程初始化怎么办?
这里提供一个简单粗暴的方法,博主也是这么干的…直接拿到进程名判断,作出相应操作即可:

每个进程创建,都会调用Application的onCreate方法,这是一个需要注意的地方,我们也可以根据当前进程的pid,拿到当前进程的名字去做判断,然后做一些我们需要的逻辑,我们这个例子,拿到的两个进程名分别是:
- 客户端进程:com.example.aidl
- 服务端进程:com.example.aidl:remote
总结
- 多进程app可以在系统中申请多份内存,但应合理使用,建议把一些高消耗但不常用的模块放到独立的进程,不使用的进程可及时手动关闭;
- 实现多进程的方式有多种:四大组件传递Bundle、Messenger、AIDL等,选择适合自己的使用场景;
- Android中实现多进程通讯,建议使用系统提供的Binder类,该类已经实现了多进程通讯而不需要我们做底层工作;
- 多进程应用,Application将会被创建多次;
结语
这篇文章断断续续写了很久,而且我相信真正使用起来的同学可能不多,选择这样一个话题我是吃力不讨好… 但是我还是希望可以在这里提供一个完整的解决方案给大家。简单的多进程使用,而且效果显著的,比如把图片选择和WebView配置到独立的进程,这个我希望可以大家行动起来。这篇文章的知识点非常多,理解起来可能不是太容易,如果有兴趣,我建议你手动去写一下,然后不理解的地方,打断点看看是什么样的运行步骤。
对于面试的同学,如果在面试过程中说到多进程,跟面试官聊得开,估计也是能加点分的,或者在实际工作中,一些使用多进程可以更好地解决问题的地方,你可以在会议中拍桌猛起,跟主管说:“我有一个大胆的想法…”,这样装 X 也不错(当然,被炒了的话就不关我的事了…)
文章不易,如果大家喜欢这篇文章,或者对你有帮助希望大家多多点赞转发关注哦。文章会持续更新的。绝对干货!!!
花费2年,字数超一万最佳总结教你Android多进程,微信微博都在用