android开发中难免会遇到要求开发多进程的应用程序。在使用中总是缺少总结,以至于在遇到问题时只能依赖于google之类的。最近看了任玉刚老师的《Android开发艺术探索》这本书,第二章就讲到了多进程的通信方式,比较全面。那么我也对学过的东西总结一下吧。
1.使用Bundle
android 在启动activity ,service,receiver时可以用Bundle实现进程间的通信,同过Intent为载体。这是进程间通信最简单的一种方式了。
Intent intent = new Intent(this,BookManagerService.class);
Bundle bundle = new Bundle();
bundle.putString("bundle","hello ipc");
intent.putExtras(bundle);
bindService(intent,mConnection,BIND_AUTO_CREATE);
接着在BookManagerService里面根据intent获取到bundle携带的信息即可。
那么问题来了,既然这么简单那就用这种方式不就好了吗?
然而在实际开发中并不止是传递一个字符这么简单。如果要传递一个对象呢?
确实,我们发现Bundle在传递参数时是可以携带可序列化的对象的。
bundle.putParcelable("ParcelableClass",books);
这种方式在同一个进程里面是可行的,然鹅在多进程中就会出错了,会出现“Class not find”这种错误。原因是定义的boos类是属于当前进程的,其他进程获取不到,即使你把该类复制到新的进程里面也不可能被反序列化出来,因为在底层上他们已经不是同一个类了。
那么bundle到底支持哪些类型的数据呢?
1.基本数据类型
2.可序列化的对象(实现了Parcellable接口,实现了 Serializable接口的对象) 
3.以及一些Android支持的特殊对象
那么要在进程之间传递对象该怎么实现呢?
gson解析成json字符串然后传递
Intent intent = new Intent(this,BookManagerService.class);
Bundle bundle = new Bundle();
Books books = new Books(1,"ming");
Gson gson = new Gson();
bundle.putString("bundle",gson.toJson(books));
intent.putExtras(bundle);
bindService(intent,mConnection,BIND_AUTO_CREATE);
这里将可序列化的对象用gson转换为json字符串,实现使用bundle传递可序列化对象。在BookManagerService里面再获取到books对象
Bundle bundle = intent.getExtras();
Log.e("mzy","bundle.getString()"+bundle.getString("bundle"));
但是书中没有提到使用json传递的方式来实现进程间通信。当然还是有更炫酷的实现方式,请往下看。
2.使用文件共享
好吧,个人感觉这种方式其实并没有多大卵用,除非是一些长期需要使用的信息使用这种方式还是挺好的,作为缓存的方式。
这个就是一个进程写文件,一个进程读文件的方式实现进程间通信的。
大体就是用的Java读写文件的方式。很简单就不列出来了,但是使用的时候还是要注意一些事情的
1.并发读/写导致数据不是最新数据
2.并发写,导致数据错误
3.SharedPreferences也是一种文件读写的方式。这个用在文件共享实现进程通信是不可取的。因为系统会对SharedPreferences进行缓存,导致数据不是最新数据。
3.使用Messenger
使用Messenger传递Message,可以实现进程间通信。其底层实现是AIDL,对AIDL进行了封装,使用起来比较简单。下面看看代码实现。
分为服务端和客户端两个进程
3.1服务端接收客户端消息
3.1.1服务端进程
在服务端创建一个Service来处理客户端的请求,创建一个Handle,并通过它来创建一个Messenger对象,再在Service的onBind中返回这个Messenger对象底层的Binder即可,说的太模糊,还是看服务端的代码吧
public class MessengerService extends Service {
    private static final String TAG = "MessengerService";
    private static class MessengerHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MyConstants.MSG_FROM_CLIENT :
                    Bundle bundle1 = msg.getData();
                    Log.i(TAG,"receive msg from Client :"+bundle1.getString("msg"));
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }
    private final Messenger mMessenger = new Messenger(new MessengerHandler());
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }
}
内容不多用一个Handle创建一个Messenger,然后在onBInd里面返回Mes的BInder,handler里面处理接收到的信息
3.1.2客户端进程
客户端首先要绑定服务端的Service,然后通过服务端返回的IBinder对象创建一个Messenger,就是通过这个Messenger对象给服务端发送消息的。,发送的消息类型为Message对象。
public class MessengerActivity extends AppCompatActivity {
    private static final String TAG = "MessengerActivity";
    private Messenger messenger;
    //绑定Service
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //获取Messenger
            messenger = new Messenger(iBinder);
            //创建Message
            Message msg = Message.obtain(null,MyConstants.MSG_FROM_CLIENT);
            Bundle data = new Bundle();
            data.putString("msg","hello i am client.");
            msg.setData(data);
            try {
                //发送消息
                messenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            //链接失败处理
        }
    };
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(MessengerActivity.this,MessengerService.class);
        bindService(intent,mConnection, Context.BIND_AUTO_CREATE);
    }
    @Override
    protected void onDestroy() {
        //记得注销
        unbindService(mConnection);
        super.onDestroy();
    }
}
好了,这样就实现了使用Messenger进程间通信了。不可以只是停留在客户端单相思的程度,当然要你来我往情意绵绵,那我们来实现一下互相之间的通信
3.2客户端与服务端交互
道理其实都差不多的,服务端在收到消息以后再给客户端发送一条消息即可。
3.2.1服务端修改
public void handleMessage(Message msg) {
     switch (msg.what){
         case MyConstants.MSG_FROM_CLIENT :
             Bundle bundle1 = msg.getData();
             Log.i(TAG,"receive msg from Client :"+bundle1.getString("msg"));
             Messenger client = msg.replyTo;
             Message replyMessage = Message.obtain(null,MyConstants.MSG_FROM_SERVICE);
             Bundle bundle = new Bundle();
             bundle.putString("reply","ok i got your message");
             replyMessage.setData(bundle);
             try {
                 client.send(replyMessage);
             } catch (RemoteException e) {
                 e.printStackTrace();
             }
             break;
         default:
             super.handleMessage(msg);
     }
 }
3.2.2客户端修改
public class MessengerActivity extends AppCompatActivity {
    private static final String TAG = "MessengerActivity";
    private Messenger messenger;
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            messenger = new Messenger(iBinder);
            Message msg = Message.obtain(null,MyConstants.MSG_FROM_CLIENT);
            Bundle data = new Bundle();
            data.putString("msg","hello i am client.");
            msg.setData(data);
            //将客户端的接收用的messenger传给服务端。
            msg.replyTo = getReplyMessenger;
            try {
                messenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
        }
    };
    private Messenger getReplyMessenger = new Messenger(new MessengerHandler());
    private static class MessengerHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MyConstants.MSG_FROM_SERVICE:
                    Log.i(TAG,"receive message from service :"+msg.getData().getString("reply"));
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(MessengerActivity.this,MessengerService.class);
        bindService(intent,mConnection, Context.BIND_AUTO_CREATE);
    }
    @Override
    protected void onDestroy() {
        unbindService(mConnection);
        super.onDestroy();
    }
}
3.3Messenger实现多进程通信小结
Messenger使用起来还是相对简单的。可以实现一对多的多进程通信(通过绑定Service)。但是由于其传递参数依赖于Bundle,所以传递的数据类型受到了限制。而且不能很好的处理高并发情况
4.使用AIDL
要不先休息一下?下一篇再写AIDL吧。看个海贼先
