Messenger實現(xiàn)進程間通信

為什么Messenger能進行進程間通信

Messenger翻譯為信使颓哮,他可以在不同的進程中傳遞Message對象

  1. 首先我們看下這個類的構(gòu)造方法钳垮,發(fā)現(xiàn)焙糟,他的底層實現(xiàn)其實就是AIDL蝗拿。
 /**
     * Create a new Messenger pointing to the given Handler.  Any Message
     * objects sent through this Messenger will appear in the Handler as if
     * {@link Handler#sendMessage(Message) Handler.sendMessage(Message)} had
     * been called directly.
     * 
     * @param target The Handler that will receive sent messages.
     */
    public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }
/**
     * Create a Messenger from a raw IBinder, which had previously been
     * retrieved with {@link #getBinder}.
     * 
     * @param target The IBinder this Messenger should communicate with.
     */
    public Messenger(IBinder target) {
        mTarget = IMessenger.Stub.asInterface(target);
    }

我們在跟一下Handler的getIMessenger方法晾捏,發(fā)現(xiàn)就是我們所熟悉的aidl的寫法。

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

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

使用Messenger如何實現(xiàn)進程間通信

  1. 首先我們先寫一個遠程服務端
public class MessengerService extends Service {
    
    private static class MessengerHandler extends Handler {

        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case 1:
                    //接收到客戶端發(fā)來的消息
                    Log.d("MessengerService", msg.getData().getString("msg"));
                    //拿到客戶端的信使
                    Messenger reply = msg.replyTo;
                    Message replyMsg = Message.obtain(null,2);
                    Bundle bundle = new Bundle();
                    bundle.putString("reply","server receive this message");
                    replyMsg.setData(bundle);
                    try {
                        //給客戶端回消息
                        reply.send(replyMsg);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    }
    //創(chuàng)建一個服務端的信使哀托,同時傳入處理消息的handler對象
    private final Messenger messenger = new Messenger(new MessengerHandler());

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //返回給客戶端binder對象
        return messenger.getBinder();
    }
}

  1. 在AndroidManifest.xml配置服務,process=":remote"使這個服務處于remote進程惦辛。
        ...
        <service
            android:name=".MessengerService"
            android:process=":remote" />
        ...
  1. 編寫客戶端邏輯
public class MessengerActivity extends AppCompatActivity {

    private static class ClientMessengerHandler extends Handler {

        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case 2:
                    //接收到服務端回的消息
                    Log.d("MessengerService", msg.getData().getString("reply"));

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

    /**
     * 客戶端處理消息的信使
     */
    private final Messenger clientMessengerHandler = new Messenger(new ClientMessengerHandler());


    private Messenger serviceMessenger;

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //通過IBinder對象,創(chuàng)建出服務端的信使
            serviceMessenger = new Messenger(service);
            Message msg = Message.obtain(null, 1);
            Bundle bundle = new Bundle();
            bundle.putString("msg","hello this is client");
            msg.setData(bundle);
            //通過這種方式仓手,把客戶端的信使傳遞給服務端胖齐,用于服務端給客戶端回消息
            msg.replyTo = clientMessengerHandler;
            try {
                //給服務端發(fā)送消息
                serviceMessenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_messenger);
        Intent it = new Intent(this,MessengerService.class);
        bindService(it,serviceConnection, Context.BIND_AUTO_CREATE);
    }
}

Messenger工作原理圖

Messenger工作原理圖

總結(jié)

  • Messenger對AIDL進行了封裝,由于他一次處理一個請求嗽冒,因此在服務端我們不需要考慮線程同步問題
  • Messenger進行數(shù)據(jù)傳遞必須將數(shù)據(jù)放到Message里面
  • 由于Messenger一次處理一個請求呀伙,所有不適用于大量并發(fā)的請求
  • Messenger作用主要是為了傳遞消息,如果我們需求需要調(diào)用服務端的具體方法添坊,Messenger無法做到剿另。(需要使用AIDL,自己定義接口來實現(xiàn)此類需求)

Thanks

鏈接: Android開發(fā)藝術探索.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子雨女,更是在濱河造成了極大的恐慌谚攒,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件戚篙,死亡現(xiàn)場離奇詭異五鲫,居然都是意外死亡,警方通過查閱死者的電腦和手機岔擂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門位喂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人乱灵,你說我怎么就攤上這事塑崖。” “怎么了痛倚?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵帖汞,是天一觀的道長。 經(jīng)常有香客問我增拥,道長劳闹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任耘戚,我火速辦了婚禮嗡髓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘收津。我一直安慰自己饿这,他們只是感情好,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布撞秋。 她就那樣靜靜地躺著长捧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪吻贿。 梳的紋絲不亂的頭發(fā)上串结,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音舅列,去河邊找鬼奉芦。 笑死,一個胖子當著我的面吹牛剧蹂,可吹牛的內(nèi)容都是我干的声功。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼宠叼,長吁一口氣:“原來是場噩夢啊……” “哼先巴!你這毒婦竟也來了其爵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤伸蚯,失蹤者是張志新(化名)和其女友劉穎摩渺,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體剂邮,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡摇幻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了挥萌。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绰姻。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖引瀑,靈堂內(nèi)的尸體忽然破棺而出狂芋,到底是詐尸還是另有隱情,我是刑警寧澤憨栽,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布帜矾,位于F島的核電站,受9級特大地震影響屑柔,放射性物質(zhì)發(fā)生泄漏屡萤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一掸宛、第九天 我趴在偏房一處隱蔽的房頂上張望死陆。 院中可真熱鬧,春花似錦旁涤、人聲如沸翔曲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至闻妓,卻和暖如春菌羽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背由缆。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工注祖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人均唉。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓是晨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親舔箭。 傳聞我的和親對象是個殘疾皇子罩缴,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353