移動架構 (六) 輕量級進程間通訊框架設計

概述

如今多進程傳遞數據使用愈來愈普遍了,在 Android 中進程間通訊提供了 文件AIDLBinderMessengerContentProviderSocketMemoryFile 等,實際開發中使用最多的應該是 AIDL ,可是 AIDL 須要編寫 aidl 文件,若是使用 AIDL 僅僅是爲了傳遞數據, 那麼 YKProBus 是你不錯的選擇。java

YKProBus

怎麼使用?

1. root/build.gradle 中添加框架 maven

allprojects {
		repositories {
			...
			maven { url 'https://jitpack.io' }
		}
	}
複製代碼

2. app/build.gradle 中添加框架 依賴

dependencies {
	        implementation 'com.github.yangkun19921001:YKProBus:1.0.1'
	}
複製代碼

3. 發送進程綁定接收進程服務

EventManager.getInstance().bindApplication(Context context,String proName);
複製代碼

4. 發送消息

EventManager.getInstance().sendMessage(int messageTag,Bundle bundle);
複製代碼

5. 接收進程中須要在清單文件註冊服務

<service       
 android:name="com.devyk.component_eventbus.proevent.service.MessengerService"
 android:enabled="true"
 android:exported="true">
    <intent-filter>
           <action android:name="com.devyk.component_eventbus.service"></action>
           <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>
複製代碼

6. 接收消息

6.1 在須要接收消息的類中實現 IMessageHandler 並實例化一個 Handler 用於接收發送進程發來的消息android

public class MainActivity extends Activity implements IMessageHandler{
  ...
    
   
    /** * 接收其它進程發送過來的消息 * * @return */
    @Override
    public Handler getHandler() {
        return new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case 0x001:
                       ...
                        break;
                }
            }
        };
    } 
  ...
}
複製代碼

6.2 註冊當前類須要接收消息git

EventManager.getInstance().registerMessager(int messageTag, Object obj);
複製代碼

框架設計大概流程

Messenger-YKProBus-.png

Messenger 源碼分析

Messenger 內部其實也是依賴 aidl 實現的進程間通訊。github

服務端

@Override
    public IBinder onBind(Intent intent) {
        return mServiceMessenger.getServiceMessenger().getBinder();
    }
複製代碼

getBinder() 跟進去app

public IBinder getBinder() {
        return mTarget.asBinder();
    }
複製代碼

mTarget 從何而來,從源碼找找框架

public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }
複製代碼

這裏是咱們實例化 服務端 Messenger 傳入的 Handler targetmaven

/** * 初始化服務端 Messenger */
    public MessengerManager() {
        if (null == mServiceMessenger)
            mServiceMessenger = new Messenger(mMessengerServiceHandler);
    }
複製代碼

那麼咱們在點擊 getIMessenger() 在看看內部實現ide

final IMessenger getIMessenger() {
        synchronized (mQueue) {
            if (mMessenger != null) {
                return mMessenger;
            }
            mMessenger = new MessengerImpl();
            return mMessenger;
        }
    }
   
複製代碼

繼續點擊 MessengerImple函數

private final class MessengerImpl extends IMessenger.Stub {
        public void send(Message msg) {
            msg.sendingUid = Binder.getCallingUid();
            Handler.this.sendMessage(msg);
        }
    }
複製代碼

這個是一個內部實現的類,能夠看到繼承的是 IMessenger.Stub 而後實現 send (Message msg) 函數,而後經過 mTarget.sendMessage(msg) 發送消息,最後在咱們傳入進去的 mMessengerServiceHandler 的 handleMessage (Message) 接收發來的消息。源碼分析

既然這裏內部幫咱們寫了 aidl 文件 ,而且也繼承了 IMessenger.Stub 咱們今天就要看到 aidl 才死心 , 好吧咱們來找找 IMessenger aidl 文件。

IMessenger-aidl-.jpg

能夠看到是在 framework/base/core/java/android/os 路徑中,咱們點擊在來看下文件中怎麼寫的

IMessenger-aidl-2.jpg

內部就一個 send 函數,看到這,你們應該都明白了,Messenger 其實也沒什麼大不了,就是系統內部幫咱們寫了 aidl 而且也實現了 aidl ,最後又幫咱們作了一個 Handler 線程間通訊,因此服務端收到了客服端發來的消息。

客服端

客服端須要在 bindServicer onServiceConnected 回調中拿到 servicer, 平時咱們本身寫 應該是這麼拿到 Ibinder 對象吧

IMessenger mServiceMessenger = IMessenger.Stub.asInterface(service);
複製代碼

可是咱們實際客服端是這樣拿到服務端的 Messenger

/** * 服務端消息是否鏈接成功 */
    private class EventServiceConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            isBindApplication = true;
            // 獲得服務信使對象
            mServiceMessenger = new Messenger(service);

            //將本地信使告訴服務端
            registerMessenger();

            String proName = ProcessUtils.getProName(mApplicationContext);
            Log.d(TAG, " EventServiceConnection " + proName);

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            isBindApplication = false;
        }
    }
複製代碼
// 獲得服務信使對象
mServiceMessenger = new Messenger(service);
複製代碼

跟進去

public Messenger(IBinder target) {
  mTarget = IMessenger.Stub.asInterface(target);
}
複製代碼

這不就是咱們剛剛說的本身實現的那種寫法吧,到這裏咱們都懂了吧,咱們平時寫的 aidl android 中已經幫咱們寫了,想當於在 aidl 中封裝下就變成了如今的 Messenger , 而咱們又在 Messenger 上封裝了下,想當於 三次封裝了,爲了使用更簡單。封裝纔是王道!

總結

咱們本身的 YKProBus 爲了進程間通訊使用更簡單方便,其實至關於在 AIDL 中的三次封裝。想要了解的能夠去看下我具體的封裝或者 Messenger 源碼。

感謝你們抽空閱覽文章,謝謝!

相關文章
相關標籤/搜索