进程间通讯

进程间通讯分为以下几种方式:

 1.Bundle,在Intent中通过通过Bundle传递数据,最简单的比如说我们自定义的app可以启动别的大型app,比如百度地图。

Intent实现的数据传递必须序列化,这是最简单的进程间通讯方式。

这里特别说明一种情况:在a进程中需要计算结果,然后计算完成后启动B进程并且将结果传递给B进程,这个过程计算的结果如果不能通过Bundle传递,如果用其他IPC会比较麻烦,这个时候就可以用另外一种方式解决:通过Intent启动B进程的一个Service组件(比如IntentService),让Service在后天进行计算,计算完毕后再启动B进程中真正要启动的组件,这样就可以直接解决跨进程的问题,核心思想是将A的计算任务转移到B进程的后台Service中去执行。

 2.通过共享文件来共享数据,一个app将数据写入到本地文件中,别的进程可以访问到本地文件并且获取数据,这个主要是用到io流读写数据,注意读写对象的时候需要将对象序列化。这种方式也是有局限性的,比如并发读写的时候数据就会可能出差错。只适用于数据同步性不高的情况下。特别说明一下SharedPreference,其底层是通过xml文件实现键值对存储。每个应用的sh文件都可以在当前包目录下查询到。因为SharePreference系统采用了缓存策略,即在内存中会有一份sharedPreference文件的缓冲,因此多进程模式下面对高并发的读写,有很大几率会丢失数据,所以不建议进程间通讯使用sharedPreference.

  3.通过Binder来通讯,会用到aidl

     3.1使用Messenger通讯,查看Messenger会发现它的原理也即是aidl封装。实现Messenger的方法:

       服务端:创建service处理客户端请求,同时创建一个Handler并且通过它来创建一个Messenger,然后在Service的OnBind中返回这个Messager对象底层 的Binder.

客户端:绑定服务端的service,用服务器返回的IBinder对象创建一个Messenger,通过这个Messenger就可以像服务端发消息了,发消息的类型是Messenger对象,如果需要回应服务单,就需要在客户端创建同服务端一样的Handler和Messenger.需要注意到是在Messenger中传输数据必须将数据放入Message中;并且Message.obj传输的对象只能是系统序列化的对象,所以非系统序列化的对象不能通过message.obj赋值

以下是自定义的Service类,即服务端:

public class IPCService1 extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();//返回Messenger的Binder.即handler
    }

    private static class IPCHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {

            switch (msg.what) {
                case 1://客户端响应返回的数据
                    Logger.d("serviceData====" + msg.getData().getString("msg"));
                    Messenger client = msg.replyTo;//获取客户端的Messenger;
                    Message message = Message.obtain(null, 2);
                    Bundle bundle = new Bundle();
                    bundle.putString("reply", "服务端已经收到请求,响应了客户端");
                    message.setData(bundle);
                    try {
                        client.send(message);

                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }

                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    }

    private final Messenger mMessenger = new Messenger(new IPCHandler());
}

客户端的Activity:

public class ThridActivity extends AppCompatActivity {

    private Messenger mMessenger;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.act_thrid);
        new Thread(new Runnable() {
            @Override
            public void run() {
                getCacheData();
            }
        }).start();
        Intent intent = new Intent(this, IPCService1.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mMessenger = new Messenger(service);//先实例化Messenger对象
            Message message = Message.obtain(null, 1);
            Bundle bundle = new Bundle();
            bundle.putString("msg", "来自于客户端的请求");
            message.setData(bundle);//Message数据封装Message数据
            //将客户端响应服务端的Messenger通过这个参数传递给服务端,这样服务端接受到数据之后就会通过这个replyMsg将数据反馈回来,从而达到接收的效果
            message.replyTo=replyMsg;
            try {
                mMessenger.send(message);//通过Messgener发送数据,让服务端接受
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

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

    //为了接受服务端的传递数据,客户端需要也定义一个Handler和Messenger
    private static class MsgHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 2://服务端回应
                    Logger.d(msg.getData().getString("reply"));
                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    }
    private Messenger replyMsg=new Messenger(new MsgHandler());
}

注意上面的Service和Activity我在清单中通过process属性声明分属于两个不同的进程。以上会发现通过Messenger来实现进程间通讯,如果消息太多的话,服务器只能一条一条的处理,是串行的方式处理,所以当面临并发消息的时候也不合适,或者说想要跨进程调用服务端的方法的时候Messenger也无法达到目的。

  4.aidl通讯

  4.ContentProvider,内容提供者,天生就是提供跨进程数据通讯的,ContentProvider也是通过Binder的原理来实现进程间通讯的,只不过系统为我们封装好了,便于使用。

  5.通过网络通讯实现数据传递,即Socket也可以实现ipc(进程间通讯);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值