Android進階筆記:Messenger源碼詳解

Messenger能夠理解爲一個是用於發送消息的一個類用法也不少,這裏主要分析一下再跨進程的狀況下Messenger的實現流程與源碼分析。相信結合前面兩篇關於aidl解析文章可以更好的對aidl有一個認識。(Android進階筆記:AIDL內部實現詳解 (一)Android進階筆記:AIDL內部實現詳解 (二)java

用法說明

先來看一下Messenger在跨進程通信時的使用方法,代碼以下:android

Service的代碼

//用來傳遞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

  1. 定義了一個MessengerHandler的內部類而且實現了handleMessage的內部回調;
  2. 建立了一個Messenger的對象,在Messenger的構造函數中傳入剛剛建立的handler實例;
  3. 在Service的onBind方法中回調messenger的getBinder()方法;

Activity的代碼

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

  1. 經過綁定Service來得到IBinder對象;
  2. 經過IBinder對象從新構造一個Messenger;
  3. 經過Messenger的send方法來發送消息;

以上就是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的例子。

總結

  1. Server端就是Handler裏面實現的MessengerImpl內部類,而後在Service裏面被實例化了。而這個aidl也是隻有一個方法(send(Message)),就是經過當前Handler來發送一個消息。

  2. 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的實現很是的類似。

相關文章
相關標籤/搜索