Messenger能够理解为一个是用于发送消息的一个类用法也不少,这里主要分析一下再跨进程的状况下Messenger的实现流程与源码分析。相信结合前面两篇关于aidl解析文章可以更好的对aidl有一个认识。(Android进阶笔记:AIDL内部实现详解 (一)、Android进阶笔记:AIDL内部实现详解 (二))java
先来看一下Messenger在跨进程通信时的使用方法,代码以下:android
//用来传递Messenger中IMessenger public class ServerService extends Service { public static final String TAG = "ServerService"; private Messenger messenger; @Override public void onCreate() { super.onCreate(); //建立一个Messenger对象 messenger = new Messenger(new MessengerHandler()); } @Nullable @Override public IBinder onBind(Intent intent) { //返回IMessenger return messenger.getBinder(); } } //用于建立Messenger的Handler class MessengerHandler extends Handler { public static final String TAG = "ServerService"; @Override public void handleMessage(Message msg) { if (msg.what == 10001) { String data = msg.getData().getString("data"); data = data == null ? "null" : data; Log.e(TAG, "handleMessage: get msg from client = (" + data + ")"); } } }
上面就是Service的代码,分析一下其实总共作了3步:markdown
public class MainActivity extends AppCompatActivity { private ServiceConnection serviceConnection; private Messenger messenger; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.e("MainActivity", "onServiceConnected: connection success !!!"); //用返回的Ibinder对象来构造一个Messenger实例 messenger = new Messenger(service); //建立一个msg Message msg = new Message(); msg.what = 10001; Bundle bundle = new Bundle(); bundle.putString("data", "hello Server"); msg.setData(bundle); try { //调用messenger的send方法 messenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { messenger = null; } }; bindService(new Intent("com.coder_f.messengerdemo.ServerService"), serviceConnection, BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); unbindService(serviceConnection); } }
Activity中作的工做其实也不复杂也是3步:ide
以上就是Messenger的使用方法。好了如今就能够根据上面的使用方法来看看Messenger内部究竟是怎么来运做的。函数
首先先来看看参数为Handler的Messenger的构造函数oop
public Messenger(Handler target) { mTarget = target.getIMessenger(); }
很简单,就是保存传入Handler的getIMessenger()方法返回的东西。那接下来就去看看getIMessenger()方法返回的是什么东西。源码分析
final IMessenger getIMessenger() { synchronized (mQueue) { if (mMessenger != null) { return mMessenger; } mMessenger = new MessengerImpl(); return mMessenger; } }
也不复杂,无非就是判断一下mMessenger是否是空而后返回一下。那mMessenger究竟是什么呢。看看它的构造函数new MessengerImpl()代码以下:this
private final class MessengerImpl extends IMessenger.Stub { public void send(Message msg) { msg.sendingUid = Binder.getCallingUid(); Handler.this.sendMessage(msg); } }
看到这里相信已经摸的差很少了,这个结构就是aidl的结构。这里猜一下应该就明白了,源码里面确定有定义了一个IMessage.aidl,并且里面还声明了一个send的方法。而这个seng的方法在Handler里面被实现了,具体就是经过Handler来发送一条消息。那么能够获得结论,最后mTarget得到的其实就是一个IMessenger.Stub的实例,里面已经实现了接口中的方法(send(Message msg))spa
事实证实确实如此,源码的位置:platform\frameworks\base\core\java\android\os\IMessenger.aidl.net
package android.os; import android.os.Message; /** @hide */ oneway interface IMessenger { void send(in Message msg); }
上面只是对构造函数的源码进行了分析,可是其实已经把Messenger的结构摸的八九不离十了;
好了既然构造函数分析的差很少了,根据流程下一步应该是经过messenger.getBinder()方法取出一个Ibinder对象经过Service来返回给Activity。那么接下来再来看看messenger.getBinder()方法:
public IBinder getBinder() { return mTarget.asBinder(); }
很清楚,调用了IInterface(mTarget就是IMessenger.Stub的实例继承了IMessenger,而IMessenger继承了IInterface)的asBInder方法返回了一个Binder(这里简单的理解其实就是返回了它本身,由于stub内部类也继承了Binder)。
service这边的代码只有这些,那根据上面的使用方法,继续来看Activity这边的代码吧。
Activity这边也有一个构造函数,参数是一个IBinder对象,这个构造函数的源码以下:
public Messenger(IBinder target) { mTarget = IMessenger.Stub.asInterface(target); }
很清楚返回的其实就是一个proxy类也就是一个binder驱动(不明白的能够看以前的博客)。
而后接下来就是调用了Messenger的send方法;那继续再来看看这个send方法的源码是怎么样的。
public void send(Message message) throws RemoteException { mTarget.send(message); }
其实就是调用了刚刚proxy的send方法吧message当参数传进去。这里面的逻辑其实就是经过这个proxy类中的IBinder对象来远程调用service中已经实现的send方法。
一目了然Messenger就是一个典型的aidl的例子。
Server端就是Handler里面实现的MessengerImpl内部类,而后在Service里面被实例化了。而这个aidl也是只有一个方法(send(Message)),就是经过当前Handler来发送一个消息。
Client端就是经过Service返回过来的IBinder类来获取一个proxy对象,经过proxy对象远程调用send方法来完成通信。
补充:若是要实现Service那边处理完消息返回给activity的话只要在activity里面也建立一个Messenger,而后把这个Messenger经过Message赋值给参数message.replyTo传过去就行了,一样Service就能够经过这个参数里面的Messenger来发送消息给activity经过activity里面handler来处理消息来完成双向通信。
注意:这里有一点就是若是不是跨进的的话Service和Activity都运行在主线程,那么Service中用于处理消息的Handler里面不能执行耗时的工做,否则会致使ActivityUI界面卡住,由于Handler是建立在Service线程(主线程)用的是主线程的Looper。若是是跨进程的话Activity这边的主线程就不会卡住(Service所在的线程会卡住)。由于在普通的aidl在proxy调用的时候(其实就是调用IBinder.transact方法时)会挂起当前线程所以在Service端执行耗时操做时activity的UI线程会卡住。而messenger和普通的aidl不一样之处在于它又添加了一个Handler,而这个Handler是运行在Service所在线程(默认为Service所在进程的主线程)而真正的Messenger.send方法只执行了一个Handler的sengmessage方法(这个方法是运行在底层binder的工做线程中,只要在这个线程中不执行耗时操做调用方所在的线程就不会被挂起过久)。所以不会卡住(Service线程可能会卡住)。这一点我感受IntentService的实现很是的类似。