美文网首页
Android进程间通信

Android进程间通信

作者: waiwaaa | 来源:发表于2018-08-29 10:23 被阅读0次

开启多进程模式

在Android中开启多进程只有一种方法,就是给四大组件(Activity、Service、Receiver、ContentProvider)在AndroidMenifest中指定android:process属性。

序列化

通过Intent和Binder传数据时,需要使用Serializable或者Parcelable,数据持久化也需要Serializable。

系统提供的Parcelable接口的类:Intent、Bundle、Bitmap,List和Map也可以序列化,前提是每个元素都是可序列化的。

所以通信的数据自定义格式基本上都需要序列化

Binder

binder.png

Android开发中,Binder主要用在Service中,包括AIDL及Messenger。普通Service中的Binder不涉及进程间通信,Messenger的底层其实是AIDL。

Android中的IPC方式

使用Bundle

在Bundle中附加需要传输给远程的数据并通过Intent发送出去

使用共享文件

A进程把数据写入文件,B进程通过读取这个文件来获取数据。可以是文本,xml,也可以是自定义的。SharedPreferences由于在内存中会有一份缓存,所以多进程时不建议使用。

使用Messenger

通过它可以在不同进程中传递Message对象,它的底层实现是AIDL,它一次处理一个请求,因此服务端不用考虑线程同步问题。
实现步骤:

  • 服务端进程
    在服务端创建一个Service来处理客户端的连接请求,同时创建一个Handler并通过它创建一个Messenger对象,然后在Service的onBind中返回这Messenger对象底层的Binder即可。
private final Messenger mMessenger=new Messenger(new MyHandler());
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }
  • 客户端进程
    首先绑定服务端的Service,绑定成功后,用服务端返回的IBinder创建一个Messenger,通过这个Messenger就可以向服务端发送消息了。
private Messenger mService;
    //
    private ServiceConnection mConn=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mService=new Messenger(iBinder);
            Message msg= Message.obtain(null, MyConstants.MSG_FROM_CLIENT);
            Bundle bundle=new Bundle();
            bundle.putString("msg","client is connect");
            msg.setData(bundle);

            try {
                mService.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
        }
    };

    //服务端的回调
    private Messenger mReplyMessenger=new Messenger(new ReplyHandler());
    private static class ReplyHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MyConstants.MSG_FROM_SERVICE:
                    Log.d(TAG,"receive msg from service:"+msg.getData().getString("msg"));
                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    }
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_messenger);

        Intent intent=new Intent(this,MessengerService.class);

        bindService(intent,mConn, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        unbindService(mConn);
        super.onDestroy();
    }

使用AIDL

Messenger本质是AIDL实现,主要是为了传递消息,无法处理大量并发。另外无法做到调用服务端方法。
AIDL通信流程:

  1. 服务端
    创建一个服务端来监听客户端的请求,然后创建AIDL文件,将给客户端的接口在这个文件中声明,在Service中实现这个AIDL接口。
  • 处理并发请求,所以要用CopyOnWriteArrayList
  • Binder会把传过来的对象重新生成新对象,RemoteCallbackList是系统提供的用于删除进程Listener的接口,内部实现线程同步,用它来注册及解注册。
  1. 客户端
    绑定服务端的Service,将服务端返回的Binder对象转换成AIDL接口所属的类型,然后就可以调用AIDL中的方法了。
  • 调用的方法可能是耗时操作,最好是在线程中去调用
  1. AIDL接口的创建

AIDL文件支持的数据类型:
基本类型(int ,long, char, boolean, double等)
StringCharSequence;
List: 只支持ArrayList (里面每个元素都必须支持)
Map: 只支持HashMap(key,value每个元素都必须支持)
Parcelable: 所有实现了Parcelable接口的对象
AIDL: 所有AIDL接口本身也可以在AIDL文件中使用。

由于代码相对较多,请在文末链接去查看实现代码。

注意点:

  • Parcelable对象和AIDL对象必须显示import进来
  • AIDL文件中用到的Parcelable对象,必须新建一个和它同名的AIDL文件,并在其中声明为Parcelable类型

使用ContentProvider

创建一个自定义的ContentProvider只需继承ContentProvider并实现6个接口方法即可。

使用Socket

建立一个ServerSocket当服务端,再建立一个Socket当客户端去连接,它们通过本地网络来进行通信。

使用场景比较

一个表格来说明优缺点及使用场景

名称 优点 缺点 适用场景
Bundle 简单易用 只能传输Bundle支持的数据 四大组件间通信
文件共享 简单易用 不适合高并发,不能即时通信 无并发,简单交换数据
AIDL 功能强大,支持一对多,实时通信 使用复杂,需处理好了线程同步 有一对多,远程调用的需求
Messenger 支持一对多串行通信,支持实时通信 不支持高并发,不支持远程调用,只能传递Bundle数据 低并发一对多即时通信,无远程调用需求,或无须返回结果的远程调用
ContentProvider 数据访问方面功能强大,支持一对多并发数据共享,可通过Call方法扩展其它操作 可理解为受约束的AIDL,主要提供CRUD操作 一对多的进程间的数据共享
Socket 功能强大,通过网络传输字节流,支持一对多并发实时通信 实现烦琐,不支持直接的远程调用 网络数据交换

最后给出Messenger,AIDL及Socket通信的完整示例,可以移步github

相关文章

网友评论

      本文标题:Android进程间通信

      本文链接:https://www.haomeiwen.com/subject/gtjziftx.html