要理解跨进程通信,首先需要理解以下几个知识点1: Android多进程指的是一个应用中存在多个进程的情况,在Android中,一般一个应用存在一个进程。多进程的情况2: 开启多进程模式是通过在 一般来说,使用多进程会存在以下几个问题: 如果你需要做一个 实现IPC方式可以分为以下几种方式4: 在 使用Messenger实现客户端和服务端双向通信 运行截图: 由于以上原因,不建议使用 利用多进程同时读写同个外部文件达到是数据交互的目的,存储形式没有限制:xml,文本,对象序列化等等。但其有着明显的缺点,由于Linux系统对文件并发读写没有限制,会导致数据不同步问题,所以该方式只适合于对数据同步要求不高的进程间通信 为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用
1 需要的知识点
1.1 进程与线程
1.2 Android中的多进程
AndroidManifest
中指定Android:process
属性<activity android:name=".SecondActivity" android:process=":twoprocess"></activity> <activity android:name=".ThirdActivity" android:process="com.yds.thirdprocess"></activity>
“:”
开头的进程属于应用的私有进程,其它应用的组件不可以与它跑在同一个进程中,而不以冒号开头的数据全局进程,其它应用通过shareUID
方式可以和它跑在同一个进程中。shareUID
:Android系统会为每个程序分配一个不同级别的UID,如果需要相互调用,只能是UID相同才行,这就使得共享数据具有了一定的安全性,每个软件之间是不能随意获得数据的,而同一个Application只有一个UID,所以Application之间不存在访问权限的问题。
1.3 数据共享方法
Application
将某些服务的Service
,Provider
或者Activity
等的数据共享出去,有如下三个办法:
android:exported="true"
,一旦设置了true
,则将会被完全暴露,可以被其它应用进程调用其暴露出去的数据。没有使用android:exported
的Service
,Provider
或者Activity
,其默认的exported
值为false
,但此时如果设置了intent filter
,则其默认值为true.android:permission="xxx.xxx.xxx"
,则你必须在Manifest中使用use-permission
才能访问应用A的东西。shareUserID
将两个软件的Uid强制设置为一样的。这种情况下必须使用具有该公司签名的签名文档才能,如果使用一个系统自带软件的ShareUID
,例如Contact,那么无须第三方签名。31.4 IPC基础概念介绍
Serialiazable
与Parcelable
:
Serialiazable
:Java提供的序列化接口Parcelable
:Android提供的序列化接口Serialiazable
与Parcelable
的区别:Serialiazable
使用简单但是需要大量I/O操作,Parcelable
使用较繁琐,主要用于内存序列化,效率高。Binder
:
详见【IPC】Binder跨进程通信机制原理2 实现IPC方式
Bundle
SharedPreferences
Messenger
AIDL
ContentProvider
Binder
连接池2.1 使用Messenger
Messenger
被称为信使,常与Message
一起使用实现跨进程通信。底层只是对Binder
的简单包装
Service
,在Service
中的onBind
里返回一个IBinder
对象。AndroidManifest
中声明服务,并将该服务放在另外的一个进程中bindService
绑定服务ServiceConnection
对象,使用服务端返回的IBinder
对象创建一个Messenger
,该Messenger
是服务端的Messenger
,可以通过该Messenger
将客户端数据发送到服务端(该方法是通过客户端向服务端传递数据,如果想从服务端向客户端传递数据,可以通过在客户端创建一个Handler
对象,然后通过该对象创建一个客户端Messenger
,然后通过message.replyTo
5将客户端的Messenger
发送到服务端,然后在服务端获取客户端创建的Messenger
,然后通过Messenger将数据发送给客户端,这样就实现了服务端向客户端传递数据)mMessenger.send(message)
来将数据发送给服务端,从而实现跨进程通信。
创建一个Service
,在Service
中的onBind
里返回一个IBinder
对象。/** * Created by yds * on 2020/4/13. */ public class MessengerService extends Service { //服务端自己的信使,为了获取客户端数据 private Messenger mMessenger; //客户端信使对象,为了将数据发送到客户端 private Messenger cMessenger; @Override public IBinder onBind(Intent intent) { mMessenger = new Messenger(new MyHandler()); System.out.println("MessengerService onBind"); return mMessenger.getBinder(); } class MyHandler extends Handler{ @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); switch (msg.what){ case 0: Message message = Message.obtain(null,1); message.arg1 = 1000; //获取客户端传递来的信使 cMessenger = msg.replyTo; try { //通过客户端信使发送服务端数据到客户端 cMessenger.send(message); } catch (RemoteException e) { e.printStackTrace(); } System.out.println("MessengerService handleMessage"); break; } } } }
AndroidManifest
中声明服务,并将该服务放在另外的一个进程中<service android:name=".MessengerService" android:process="com.yds.test.messengerservice"/>
public class MainActivity extends AppCompatActivity { //服务端信使,为了发送数据到客户端 private Messenger mMessenger; //客户端自己的信使,为了获取服务端数据 private Messenger cMessenger; private static class MyHandler extends Handler { @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); switch (msg.what) { case 1: System.out.println("Service Data: " + msg.arg1); break; } } } private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mMessenger = new Messenger(service); cMessenger = new Messenger(new MyHandler()); if (mMessenger != null) { Message msg = Message.obtain(null, 0); //将客户端自己的信使放在Message里传递到服务端 msg.replyTo = cMessenger; try { mMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } } @Override public void onServiceDisconnected(ComponentName name) { mMessenger = null; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent(this, MessengerService.class); bindService(intent, mServiceConnection, BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); unbindService(mServiceConnection); } }
2.2 使用Bundle
Bundle
是final
类型,不可被继承,它实现了Parcelable接口,是一个特殊的Map类型,支持进程间通信。
使用Bundle进行进程间通信,其实还是通过Messenger+Message来实现的,核心代码如下:mMessenger = new Messenger(service); Message msg = Message.obtain(null, 0); Bundle bundle = new Bundle(); bundle.putString("IPC", "Bundle"); bundle.putInt("Number", 20); msg.setData(bundle); try { mMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); }
2.3 使用SharedPreferences
SharedPreferences
并不适合存储大量数据和频繁改变数据,只能用于轻量的存储,高并发读/写时有可能会丢失数据。SharedPreferences
存在以下性能问题6:
MODE_MULTI_PROCESS
,SharedPreferences
在跨进程频繁读写有可能导致数据全部丢失。根据线上统计,SharedPreferences
大约会有万分之一的损坏率。SharedPreferences
文件的加载使用了异步线程,而且加载线程并没有设置优先级,如果这个时候读取数据就需要等待文件加载线程的结束。这就导致主线程等待低优先线程锁的问题,比如一个 100KB
的 SP
文件读取等待时间大约需要 50 ~ 100ms
,并且建议大家提前用预加载启动过程用到的 SP
文件。commit()
还是 apply()
,即使我们只改动其中一个条目,都会把整个内容全部写到文件。而且即使我们多次写同一个文件,SP
也没有将多次修改合并为一次,这也是性能差的重要原因之一。apply
机制,在崩溃或者其它一些异常情况可能会导致数据丢失。所以当应用收到系统广播,或者被调用 onPause
等一些时机,系统会强制把所有的 SharedPreferences
对象的数据落地到磁盘。如果没有落地完成,这时候主线程会被一直阻塞。这样非常容易造成卡顿,甚至是ANR
,从线上数据来看 SP
卡顿占比一般会超过 5%
。SharedPreferences
进行跨进程通信,特别是SharedPreferences
进行跨进程通信不安全。2.4 使用文件共享
2.5 使用AIDL
(Remote Procedure Call,RPC)
方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)
来公开服务的接口。很多IPC通信方式都是基于AIDL
的。如Service
、ContentProvider
等AIDL
的简单使用可见:AIDL简单使用待续
参考文章
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算