进程间通讯篇系列文章目录:
Android查缺补漏(IPC篇)-- 进程间通讯基础知识热身
Android查缺补漏(IPC篇)-- Bundle、文件共享、ContentProvider、Messenger四种进程间通讯介绍
Android查缺补漏(IPC篇)-- 款进程通讯之AIDL详解
Android查缺补漏(IPC篇)-- 跨进程通讯之Socket简介及示例
在Android中进程间通信的实现方式有多种,包括:Bundle、文件共享、ContentProvider、Messenger、AIDL、Socket等等,其各有各的优缺点,接下来就分别介绍一下上述各种进程间的通信方式及实现。
一、BundleActivity、Service、Receiver都支持Intent中传递Bundle数据,由于Bundle实现了Parcelable接口,所以它可以方便的在不同的进程间传输。
传输的数据必须能够被序列化:
基本类型
String类型
CharSequence
实现了Parcelable接口的对象
实现了Serializable接口的对象
List
IBinder类型
SparseArray
二、文件共享文件共享作为进程间通讯时,无法解决并发读写时所带来的问题,所以只适合在对数据同步要求不高的进程间通讯。
其实SharedPreferences也属于文件共享方式的一种,sp是android中提供的一种轻量级存储方案,通过键值对的方式来存储数据,底层用xml文件来存储键值对。每个应用的sp文件放在当前包所在的data目录下,位于/data/data/package_name/shared_prefs目录下。由于系统对它的读写有一定的缓存策略,即在内存中会有一份sp文件的缓存,因此在多进程模式下,它变得不可靠。
三、ContentProviderContentProvider在前面介绍四大组件时就已经介绍过了,这里就不多说了,详见《Android查缺补漏--ContentProvider的使用》
四、Messenger 1、Messenger是什么?通过Messenger可以很方便的在不同的进程之间传递Messager对象,在Messager对象中就可以放入我们需要传递的数据。我们知道,跨进程传输数据有很多种方式,其中AIDL最为强大也最为常用,而Messenger即相当于AIDL的简化版,其底层也是采用AIDL实现,是一种轻量级的跨进程传输方案。
所谓简化版常常功能有限,Messenger也不例外,相对于AIDL它的功能确实弱化了不少,在方便使用的同时它一次只能处理一个请求。
2、实现一个简单的Messenger通讯实现一个Messenger需要在两个进程中做以下操作:
为了避免歧义,我们提前约定,以下所说的服务端若不做特别说明默认指Service所在的进程。在服务端:首先,创建一个Service充当服务端进程,然后在Service中创建一个Messenger,因为创建Messenger时需要传入一个Handler,所以还要创建一个Handler,接收数据的操作就在Handler中,最后在Service的onBind中返回这个Messenger的Binder即可。
示例代码如下:
/** * Created by liuwei on 18/1/29. */ public class MessengerService extends Service { private static final String TAG = MessengerHandler.class.getSimpleName(); // 创建一个Handler,处理消息用 private class MessengerHandler extends Handler{ @Override public void handleMessage(Message msg) { switch (msg.what) { case AppConstants.MSG_FROM_CLIENT: // 接收客户端发来的消息 Log.i(TAG, "handleMessage: MSG_FROM_CLIENT:" + msg.getData().getString("msg")); break; default: super.handleMessage(msg); } } } // 创建Messenger private Messenger messenger = new Messenger(new MessengerHandler()); @Nullable @Override public IBinder onBind(Intent intent) { // 返回Messenger的Binder return messenger.getBinder(); } }这里要想让Service跑在另外一个进程中需要在AndroidManifest文件中添加process节点:
<service android:name=".messager.MessengerService" android:process=":remote" />在客户端:就像绑定一个普通的Service一样,通过bindService方法链接Service即可,不同点是,需要在ServiceConnection接口中的onServiceConnected方法中通过参数中的IBinder创建一个Messenger对象,通过这个Messenger对象即可向服务端发送message消息。
示例代码如下:
public class MessengerActivity extends AppCompatActivity { private final static String TAG = MessengerActivity.class.getSimpleName(); Button btn_bind_messenger; Intent intent; Messenger messenger; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_messenger); btn_bind_messenger = ViewUtils.findAndOnClick(this, R.id.btn_bind_messenger, mOnClickListener); intent = new Intent(this, MessengerService.class); } private View.OnClickListener mOnClickListener = new View.OnClickListener() { @Override public void onClick(View v) { switch (v.getId()){ case R.id.btn_bind_messenger: // 绑定Service bindService(intent, connection, BIND_AUTO_CREATE); break; } } }; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 链接messenger成功,利用service创建一个Messenger messenger = new Messenger(service); // 向服务端发送一条消息 Message message = Message.obtain(null, AppConstants.MSG_FROM_CLIENT); Bundle bundle = new Bundle(); bundle.putString("msg", "client bind messenger succeed!"); message.setData(bundle); try { messenger.send(message); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { messenger = null; } }; @Override protected void onDestroy() { unbindService(connection); super.onDestroy(); } }