汝阳网站开发,合肥网站建设服务公司,网站网页的区别与联系,网站导航是什么一、简介
进程间通讯#xff08;InterProcess Communication#xff09;
指在不同进程之间传播或交换信息#xff0c;Android是基于Linux 系统的#xff0c;在Linux 中进程间是不能直接通讯的#xff0c;IPC就是为了解决这一问题
每个操作系统都有相应的IPC机制#x…一、简介
进程间通讯InterProcess Communication
指在不同进程之间传播或交换信息Android是基于Linux 系统的在Linux 中进程间是不能直接通讯的IPC就是为了解决这一问题
每个操作系统都有相应的IPC机制Android中一个进程会对应一个虚拟机实例不同的虚拟机在内存分配上有不同的地址空间
只有在多进程的环境下才会使用IPC进行通讯
二、使用场景
多模块应用由于Android应用受到系统的最大内存限制为了获得更多的内存空间将不同的模块放在不同的线程中此时需要用到跨进程通信其它应用获取其它应用里的数据比如获取通讯录和短信
三、实现多进程
Android默认是运行在包名的进程中可以通过修改AndroidManifest文件在 application 标签下添加 android:process 属性可以修改Android默认的进程名字
给四大组件Activity Service Broadcast ContentProvider设置android:process属性来实现多进程
四、造成的问题
多进程会造成Application的多次创建当一个组件需要运行在新的进程中时实际的创建过程就相当于又重新启动了一次应用就会创建Application。而运行在不同进程中的组件不仅属于不同的虚拟机而且其Application也是不同的。多进程会导致静态成员和单例完全无效由于不同进程都被分配了独立且不同的虚拟机其在内存分配上有这不同的地址空间。这就会导致在着一个类的多个副本各自修改互不影响。多进程模式下线程的同步机制也会失效因为不同的进程其线程不所属同一内存那么无论是对象锁还是类锁锁本身都不是同一个了。多进程模式下SharedPreferences风险会增大SharedPreferences底层是通过文件读写实现的并发操作可能会造成问题。
在不同进程中的组件如果使用内存来通讯都会存在隐患或者直接失败。这就是多进程带来的最主要的影响。
五、Android中的跨进程通讯IPC
利用Bundle 在Android开发中 ActivityServiceReceiver 都支持在 Intent 中传递 Bundle 数据而 Bundle实现了 Parcelable 接口以键值对的方式保存数据可以在不同的进程间进行传输。 可以将其视为一个容器其支持基本数据类型String、int、boolean、byte、float、long、double以及它们对应的数据。当需要传递对象或对象数组时被传递的对象必须实现Serialiable或Parcelable接口。 Intent intent new Intent(MainActivity.this, SecondActivity.class);
Bundle bundle new Bundle();
bundle.putString(msg, message);
intent.putExtras(bundle);
startActivity(intent);
使用文件共享 通过共享文件不同的进程可以使用读写文件的方式交换数据 不要使用SharedPreferences去做跨进程通讯原则上它不支持多进程。虽然它本质上也是一个文件但是由于它在应用运行时会在内存中加载缓存然而进程间是不能内存共享的每个进程操作的SharedPreferences都会是一个单独的实例这就会导致安全性问题这个问题只能通过多进程间其它的通信方式或者是在确保不会同时操作SharedPreferences数据的前提下使用SharedPreferences来解决。 使用ContentProvider ContentProvider提供一种应用管理其自身和其他应用所存储数据的能力并提供与其他应用共享这些数据的方法。它会封装数据并提供用于定义数据安全性的机制。无论你是否需要和其他应用分享数据你都可以使用ContentProvider去访问这些数据虽然当无需和其他应用共享数据时没必要使用它。系统预置了许多ContentProvider比如通话记录通讯录信息等只需要通过ContentProvider就可以拿到这些信息。ContentProvider以一个或多个表的形式将数据呈现给外部应用这些表与关系型数据库中的表类似。行表示提供程序收集的某种类型数据的实例行中的每一列表示为一个实例所收集的单个数据。 ContentProvider 的底层数据可以是 SQLite 数据库可以是文件也可以是内存中的数据。 使用场景
通过实现代码访问其他应用中的现有的ContentProvider用来获得数据创建新的ContentProvider与其他应用共享数据。
使用Messenger Messenger是一种轻量级的 IPC 方案可以在不同进程中传递 Message 对象它一次只处理一个请求。Messenger通过Handler将Message发送到另一个进程实现了进程间通信底层依然是使用了Binder机制其本质上也是基于AIDL实现的。 Messenger的缺点 服务端是以串行的方式在处理消息不太适合用来出来大量的并发请求。主要作用是传递消息不太适合用来跨进程调用方法。 使用方式构建一个运行在独立进程中的服务端Service创建Messenger将Messenger的binder返回给Service的onBind方法。然后接收客户端Messege需要用Handler接收
服务端
public class MessengerService extends Service {/*** 处理客户端消息并用于构建Messenger*/private static class MessengerHandler extends Handler {Overridepublic void handleMessage(NonNull Message msg) {switch (msg.what) {case 100:System.out.println(msg.getData().getString(data));sendToClient(msg);break;}}}/*** 给客户度发送消息*/private static void sendToClient(Message message) {Messenger client message.replyTo; //通过 message拿到客户传递过来的 Messenger通过该对象发送message//当然回传消息还是要通过messageMessage msg Message.obtain(null, 100);Bundle bundle new Bundle();bundle.putString(data, 客户端, 我收到你的消息了);msg.setData(bundle);try {client.send(msg);} catch (RemoteException e) {e.printStackTrace();}}/*** 构建Messenger对象*/private final Messenger mMessenger new Messenger(new MessengerHandler());NullableOverridepublic IBinder onBind(Intent intent) {//将Messenger对象的Binder返回给客户端return mMessenger.getBinder();}
}
注册service service android:name.messenger.MessengerServiceandroid:process:messengerprocess/
客户端
class MainActivity : ComponentActivity() {private var mService: Messenger? nullprivate lateinit var btnMsg: Buttonoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)btnMsg findViewById(R.id.btn_msg)//绑定servicebindService(Intent(this, MessengerService::class.java),connection, Context.BIND_AUTO_CREATE)btnMsg.setOnClickListener {mService?.let {//创建消息通过Bundle传递数据var message Message.obtain(null, 100)message.data Bundle().apply {putString(data, 服务端我给你发送消息了)}//将客户端的Messenger对象传递给服务端才能让双方互相通信message.replyTo mClientMessenger//像服务端进程发送消息it.send(message)}}}/*** 客户端Messenger对象*/private val mClientMessenger: Messenger Messenger(MessengerHandler())/*** 用于构建客户端的Messenger对象并处理服务端的消息*/private class MessengerHandler : Handler() {override fun handleMessage(msg: Message) {when (msg.what) {100 - {println(msg.data.getString(data))}}}}private val connection: ServiceConnection object: ServiceConnection {override fun onServiceConnected(name: ComponentName?, ibinder: IBinder?) {mService Messenger(ibinder)}override fun onServiceDisconnected(name: ComponentName?) {}}override fun onDestroy() {//解绑serviceunbindService(connection)super.onDestroy()}
}
AIDL AIDL底层也是通过Binder实现的。 Messenger 是以串行的方式处理客户端发来的消息如果大量消息同时发送到服务端服务端只能一个一个处理所以大量并发请求就不适合用 Messenger 而且Messenger 只适合传递消息不能跨进程调用服务端的方法。AIDL 可以解决并发和跨进程调用方法的问题 支持数据类型 八种基本数据类型byte、char、short、int、long、float、double、booleanStringCharSequence实现了Parcelable接口的数据类型List 类型。List承载的数据必须是AIDL支持的类型或者是其它声明的AIDL对象Map类型。Map承载的数据必须是AIDL支持的类型或者是其它声明的AIDL对象 aidl跨进程通信的步骤 创建aidl文件build后生成aidl对应的java文件创建服务端Service创建客户端ActivitybindService()获取IBinder的proxy Socket Socket也称作“套接字“是在应用层和传输层之间的一个抽象层它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用以实现进程在网络中通信。 分为流式套接字和数据包套接字分别对应网络传输控制层的TCP和UDP协议