迎接Follow作者的GitHub, 关切自己的简书. 别的仿照效法Android目录.

Messenger,信使,可应用它进行进度间的通信,而Messenger对Service的呼吁选用队列的不二秘技,由此它不匡助二十八线程通讯。

  • 金沙国际官网 ,例行的选拔Service,大家都以在瑟维斯Connection的回调中强转成自个儿的service,
    • 下边这种是绝非在xml中展开进度的,那样使用没格外。

不久前在读书Android开荒格局索求这本书,看到Messenger的跨进度通讯,感觉书上讲得科学,所以在此间做个总括。Messenger的笔触非常粗略,通过它可在差别进度传递Message对象,大家在Message中归入大家需求传递的多少,就能够轻便完成数据的进程间传递了。Messenger的底层是AIDL,它对AIDL做了打包,使大家能够更简明地张开进程间通讯。

大家好,笔者系苍王。
以下是本身这么些系列的有关文章,有意思味能够参见一下,能够给个喜欢也许关切小编的篇章。

金沙国际官网 1Messenger

走访官方文书档案对于Messenger的分解:

public class MessengerService extends Service {private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { if (msg.what==MSG){ Toast.makeText(MessengerService.this, msg.getData().getString, Toast.LENGTH_SHORT).show(); } }}; private Messenger messenger = new Messenger; @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. return messenger.getBinder(); }}

[Android]如何做叁个崩溃率少于千分之三噶应用app–章节列表

本文的合集已经创作成书,高等Android开采深化实战,款待各位读友的提交涉指点。在京东就可以购买:

Reference to a Handler, which others can use to send messages to it. This allows for the implementation of

  private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder iBinder) {
            ProcessService processService  = (ProcessService) iBinder;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

拜会这些服务端代码,我们利用了四个Handler管理客商端发送的Message,从Message抽出大家所需的多寡。大家新建了叁个Messenger对象,从构造参数大家得以见见它和handler相关联。大家在onBind()方法中回到了messenger中的binder对象。

金沙国际官网 2

金沙国际官网 3Android

message-based communication across processes, by creating a Messenger pointing to a Handler in one process,

  • 而是一旦在xml中增加android:process=”xxxx” 后
    ,上边的不二法门就不得以用了!

  • 那就供给使用Messenger,何况Messenger在开进度可能不开进程中都可以选取,所以提出采纳Messenger举行运动与service间的通讯,并且动用起来也大致

  • 首先必要在service中创制对象,必要多少个Handler来进展链接

是因为大家管理的是跨进程通信,所以别忘了在Manifest文件中给Service加上process属性.

Android组件化架构热卖中

进程之间不可能分享内部存款和储蓄器数据, 不过足以开展通讯, 除了简约的Intent通讯,
也足以利用Messenger, Messenger基于AIDL达成, 顺序实施, 不帮衬并发.
为了区别通讯的内容, 大家暂定发送数据是顾客端, 接收数据是服务端.
本文介绍Messenger的运用格局, 含有德姆o.

and handing that Messenger to another process.

<service android:name=".MessengerService" android:process=":remote"/>

组件化群1已经满额,进来的能够加群2 763094035

本文源码的GitHub下载地址

顾客端和服务端可相互持有对方的Messenger来张开通信,下边大家来拜谒现实的兑现。

    public static final int MSG_1 = 1;
    public static final int MSG_2 = 2;
    public static final int MSG_3 = 3;

    private Messenger mMessenger = new Messenger(mHandler);

    private static Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {

            switch (msg.arg1) {
                case MSG_1:
                    String msg1 = msg.getData().getString("msg");
                    L.d( " msg 1 " + msg1);
                    break;
                case MSG_2:
                    L.d( " msg 2 ");
                    break;
                case MSG_3:
                    L.d( " msg 3 ");
                    break;
                default:
                    break;
            }

        }
    };
//在onBind的回调中写上Messenger的binder
 @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }
//好了,service中的代码这样就算完成了

我们知道,三个施用的长河暗中同意名叫包名,应用内的兼具组件都运作在那一个历程内,就算想让某些组件独立运行在另多少个进程,那么则增加process属性,这里的“:remote”全程应该是包名:remote,省去了方今的包名。

上一节,介绍了运用AIDL的经过通讯框架。
这一节给大家介绍Messenger的通讯框架,而Messenger其意思是“信使”的意味
运用Messenger的优势在于
1.实在传递的是Message,能够复用消息池
2.支撑音信回调
3.无需编写aidl

顾客端发送数据到服务端, 服务端收到数量反映回看客端.

在eclipse下开创多少个工程,分别为顾客端和服务端:

  • 下一场正是activity中的代码
public class MainActivity extends AppCompatActivity { private Messenger messenger; public static final int MSG = 1; private Button btn; private ServiceConnection connection = new ServiceConnection(){ @Override public void onServiceConnected(ComponentName name, IBinder service) { messenger = new Messenger; Message message = Message.obtain; Bundle bundle = new Bundle(); bundle.putString("msg","helloworld"); message.setData; try { messenger.send; } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn =  findViewById(R.id.bindService); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick { Intent intent = new Intent(MainActivity.this,MessengerService.class); bindService(intent,connection,BIND_AUTO_CREATE); } }); } @Override protected void onDestroy() { unbindService(connection); super.onDestroy(); }}

金沙国际官网 4

接收反馈数据

MainActivity作为客户端, 发送消息. 首先创设音讯的Handler类,
用于收纳服务端的申报, 承继Handler, 重写handleMessage方法,
msg.what类型, msg.getData()数据.

private static class MessengerHandler extends Handler { private Context mContext; public MessengerHandler(Context context) { mContext = context.getApplicationContext(); } @Override public void handleMessage(Message msg) { switch  { case ParasConsts.MSG_FROM_SERVICE: String content = String.valueOf("客户端 - 收到信息: " + msg.getData().getString(ParasConsts.REPLY_ARG)); Toast.makeText(mContext, content, Toast.LENGTH_SHORT).show(); break; default: super.handleMessage; break; } }}

使用Handler创建Messenger.

mReplyMessenger = new Messenger(new MessengerHandler(getApplicationContext;// ...msg.replyTo = mReplyMessenger;

金沙国际官网 5

以此代码大家也相比熟练了,跟平日bindService在客户端和服务端在同等进度的写法相似。分裂在于应用了Messenger.同样地我们在客商端也要新建三个Messenger对象,在构造参数里传到重回的binder对象。我们在Message中纳入大家要的多寡,借助的是Bundle,最后用messenger.send;发送过去就可以。

Messenger通讯原理图

连天服务发送数据

创建ServiceConnection类, 实现onServiceConnected方法.
成立信使Messenger, 创立新闻Message,
在Message中增添系列化数据msg.setData(), 设置接收反馈msg.replyTo.
Messenger发送数据send.

private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mMessenger = new Messenger; Message msg = Message.obtain(null, ParasConsts.MSG_FROM_CLIENT); Bundle data = new Bundle(); data.putString(ParasConsts.MSG_ARG, "Hello, I'm Spike, your friends."); msg.setData; // 需要设置Reply的Messenger. msg.replyTo = mReplyMessenger; try { mMessenger.send; } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { }};

小心信使: Messenger, 音信: Message, 拼写略有区别.

客商端的落到实处,创设顾客端的Messenger,使用Messenger的构造方法指向三个handler实例,此handler用于拍卖服务端发过来的新闻。

//首先绑定服务
  bindService(new Intent(this , ProcessService.class) , mConnection , Context.BIND_AUTO_CREATE );
//然后就是在ServiceConnection的回调中得到Messenger的对象

  private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder iBinder) {

            mMessenger = new Messenger(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
//得到Messenger的对象就可以使用它进行发送信息了,它需要一个message对象。
 public void btnOnClick(View view){
        Message message = new Message();
        message.arg1 = ProcessService.MSG_1;
        message.getData().putString("msg" , "this is msg");
        try {
            mMessenger.send(message);
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    }

咱俩运维一下主次,可知服务端收到了Messenger发来的新闻。

Messenger继承了Parcelable接口,能够视作连串化对象用于传输。
此处能够流传Handler,Handler里面有隐含IMessenger对象

绑定服务

添加Connection, 使用Context.BIND_AUTO_CREATE, 绑定自动创立.

public void bindService(View view) { Intent intent = new Intent(this, MessengerService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE);}

解绑服务unbindService.

public void unbindService(View view) { try { unbindService(mConnection); Toast.makeText(view.getContext(), "解绑成功", Toast.LENGTH_SHORT).show(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(view.getContext(), "未绑定", Toast.LENGTH_SHORT).show(); }}

绑定服务一定需求解绑服务, 幸免走漏. 若无注册, 解绑会发生非常.

服务端担当接收数据, 收到给顾客端反馈.

MessengerService接轨Service, 展现顾客端音信msg.getData().
反馈新闻的Messenger采取客商端传递的, 创造音讯增加内容,
使用顾客端的Messenger传递给顾客端.

而顾客端通过onServiceConnected得到服务端的Messenger,使用此Messenger给服务端发送音讯,客户端的Messenger通过Message的replyTo传递给服务端。

  • 与此相类似不管xml中开了经过也许尚未开,都足以用地点的主意实行与劳动时期的简练通讯

金沙国际官网 6776440378629156779.png

     /**
     * 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();
    }

管理与申报数据

/** * 信使的持有, 处理返回信息 */private static class MessengerHandler extends Handler { private Context mContext; public MessengerHandler(Context context) { mContext = context.getApplicationContext(); } @Override public void handleMessage(Message msg) { switch  { case ParasConsts.MSG_FROM_CLIENT: // 收到消息 String content = String.valueOf("服务端 - 收到消息: " + msg.getData().getString(ParasConsts.MSG_ARG)); Toast.makeText(mContext, content, Toast.LENGTH_SHORT).show(); // 回复消息 Messenger client = msg.replyTo; Message reply = Message.obtain(null, ParasConsts.MSG_FROM_SERVICE); Bundle data = new Bundle(); data.putString(ParasConsts.REPLY_ARG, "消息已经收到"); reply.setData; // 发生Reply的信息 try { client.send; } catch (RemoteException e) { e.printStackTrace(); } break; default: super.handleMessage; } }}

😉

在Messenger传输数据供给将数据归入Message.大家都掌握,跨进度运输的数码必要贯彻系列化,所以Messenger和Message必定达成了Parcelable接口,看下源码

抑或传播IBinder对象,Stub当中设有IMessenger对象

绑定接收数据

行使Handler创造服务端的Messenger

mMessenger = new Messenger(new MessengerHandler(getApplicationContext;

绑定Handler, 与客商端沟通.

@Nullable @Override public IBinder onBind(Intent intent) { return mMessenger.getBinder();}

暗中认可重回null.

顾客端, 使用Messenger传递音讯Message, Message中增添连串化数据Bundle;
服务端, 使用Handler分析获取的Message, 通过辨认类型, 获取数据.
Messenger使用特别鲜明, 易于决定, 是轻松进度通信的首推.

OK, that’s all! Enjoy it!

金沙国际官网 7

public final class Message implements Parcelable

public final class Messenger implements Parcelable
    /**
     * 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);
    }

1publicclassMainActivityextendsActivity {23privatestaticfinalString TAG
= “–DEBUG–“;45//用于运维service的ACTION6privatestaticfinalString
START_SERVER_ACTION =
“com.young.server.START_SERVICE”;7privatestaticfinalintWHAT_ON_TO_SERVICE
= 1;8privatestaticfinalintWHAT_ON_TO_CLIENT = 2;910privateButton
mBindBtn;11privatebooleanisBindService
=false;1213@Override14protectedvoidonCreate(Bundle savedInstanceState)
{15super.onCreate(savedInstanceState);16setContentView(R.layout.activity_main);17mBindBtn
=(Button)
findViewById(R.id.bind_service);18mBindBtn.setOnClickListener(newOnClickListener()
{19@Override20publicvoidonClick(View v)
{21bindService(newIntent(START_SERVER_ACTION), conn,
Context.BIND_AUTO_CREATE);22}23});24}2526//client端Handler,用于拍卖server端发来的音讯27privateHandler
mClientHandler =newHandler(newCallback()
{28@Override29publicbooleanhandleMessage(Message msg)
{30switch(msg.what) {31caseWHAT_ON_TO_CLIENT:32Log.v(TAG,
“顾客端收到服务端发来的消息!”);33break;3435default:36break;37}38returnfalse;39}40});4142//client端Messenger43privateMessenger
mClientMessenger
=newMessenger(mClientHandler);4445privateServiceConnection conn
=newServiceConnection()
{4647@Override48publicvoidonServiceDisconnected(ComponentName name)
{49Log.v(TAG, “服务已断开”);5051isBindService =false;52mClientMessenger
=null;53}5455@Override56publicvoidonServiceConnected(ComponentName name,
IBinder service) {57Log.v(TAG, “服务已链接”);5859isBindService=true;60//获得server端信使Messenger实例61Messenger serverMessenger
=newMessenger(service);62//向server端发送的音信63Message toServerMessage
= Message.obtain(null,
WHAT_ON_TO_SE福特ExplorerVICE);64//通过replyTo把client端的通讯员传递给service65toServerMessage.replyTo
=mClientMessenger;66try{67serverMessenger.send(toServerMessage);68}catch(RemoteException
e) {69e.printStackTrace();70}71}72};7374protectedvoidonStop()
{75if(isBind瑟维斯)76unbindService(conn);77super.onStop();78};79}

Message的载体有what,arg1,arg2,Bundle,object和replyTo,在一直以来进度内,obj很常用,可是在跨进程中就特别了,唯有系统提供的Parcelable对象才方可因而它举办传输,我们相依为命定义的Parcelable对象是望眼欲穿透过它传输的。然而大家还应该有Bundle,只要对象达成了Parcelable接口,利用bundle.putExtra(key,object)就能够传递数据了,这里我们只演示传递String类型数据。

其实Handler中IMessager达成指标是MessengerImpl

😉

接下去大家再来看看服务端怎么着恢复客商端发送的新闻。当服务端接收到顾客端的消息时,我们也新建一个Messenger对象回复顾客端,代码如下

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

金沙国际官网 8

//重点在这句话Messenger messenger = msg.replyTo;Message replyMessage = Message.obtain(null,REPLYMESSAGE);Bundle bundle = new Bundle();bundle.putString("reply","好的我知道了");replyMessage.setData;

此地IMessenger是调用Handler的send方法来发送新闻的。

劳动端Service的兑现,服务端接收到客商端的消息之后,通过Message的replyTo收取客商端的Messenger,使用此Messenger给顾客端发送消息,那就落到实处了经过之间的双向通讯。

messenger对象由replyTo赋值。而replyTo来自客商端的Messenger,那样两边就营造联系。再看看顾客端的退换,大家新建了Handler对象和Mssenger对象。

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

服务端通过Messenger的getBinder方法将IBinder对象返给客商端,用于分享服务端的Messenger。

private Handler getReplyHandler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what==REPLYMESSAGE){ Toast.makeText(MainActivity.this,msg.getData().getString,Toast.LENGTH_SHORT).show(); } }};private Messenger getReplyMessenger = new Messenger(getReplyHandler);

种种Message个中也富含了一个replyTo的变量顾客回调

😉

然后大家需求把接受服务端回复的Messenger通过Message的replyTo参数字传送递给服务端,这句话有一点点难精晓,多看几回。

    /**
     * Optional Messenger where replies to this message can be sent.  The
     * semantics of exactly how this is used are up to the sender and
     * receiver.
     */
    public Messenger replyTo;

金沙国际官网 9

private ServiceConnection connection = new ServiceConnection(){ @Override public void onServiceConnected(ComponentName name, IBinder service) { messenger = new Messenger; Message message = Message.obtain; Bundle bundle = new Bundle(); bundle.putString("msg","成功进行跨进程通信!"); message.setData; //这句话与服务端的Messenger messenger = msg.replyTo;相对应,缺一不可 message.replyTo = getReplyMessenger; try { messenger.send; } catch (RemoteException e) { e.printStackTrace(); } }

就那多少个步骤Messenger独立的贯彻了Parcelable和利用aidl的通讯格局

1publicclassRemoteServiceextendsService {2privatestaticfinalString TAG =
“–DEBUG–“;34privatestaticfinalintWHAT_ON_TO_SERVICE =
1;5privatestaticfinalintWHAT_ON_TO_CLIENT =
2;67//server端handler,用来拍卖client发来的音讯8privateHandler
mServerHandler =newHandler(newCallback()
{9@Override10publicbooleanhandleMessage(Message msg) {11switch(msg.what)
{12caseWHAT_ON_TO_SE揽胜极光VICE:13Log.v(TAG,
“收到顾客端发来的新闻”);14//server端得到client端的投递员Messenger15Messenger
clientMessenger =msg.replyTo;16Message toClientMsg =
Message.obtain(null,
WHAT_ON_TO_CLIENT);17try{18//使用顾客端Messenger向顾客端发送音讯19clientMessenger.send(toClientMsg);20}catch(RemoteException
e)
{21e.printStackTrace();22}23break;2425default:26break;27}28returnfalse;29}30});3132//server端信使Messenger33privateMessenger
mServerMessenger
=newMessenger(mServerHandler);3435@Override36publicIBinder onBind(Intent
intent) {37returnmServerMessenger.getBinder();38}

再运转一下主次

接下去我们介绍一下Modular框架是用Messenger通讯设计。
分裂于上一节介绍的ModularArchitecture的aidl中通讯是1对1的通信,Modular提供的通讯框架是因此1对多的出殡和埋葬方式来传递的。

😉

金沙国际官网 10230912919011775556.png

以下是Messenger的挂号流程图

金沙国际官网 11

终极再放上一张Messenger的行事规律,找不到书上的原图,只好本人画了。

金沙国际官网 12

再来看看服务端service的扬言,因为要在别的进度中运转service,所以设置android:exported为true,另外还为service到场运维了权力。

金沙国际官网 13Messenger.jpg

Messenger注册流程图

😉

1.各类模块初阶化时起步一个新闻队列来监听音信。

金沙国际官网 14

    @Override
    public void init() {
        mBaseModule = this;
        //启动线程接收消息
        mWorkThread = new WorkThread();
        mWorkThread.start();
        //注册跳转路由
        OkBus.getInstance().register(Constants.ROUTER_OPEN_URL, new Event() {
            @Override
            public void call(Message msg) {
                String url = (String) msg.obj;
               //实际跳转使用的Router               
               Router.openLocalUrl(BaseAppModuleApp.getBaseApplication(), url);
            }
        }, Bus.UI); //线程参数
    }

    public class WorkThread extends Thread {
        Handler mHandler;
        public Messenger clientHandler;

        @Override
        public void run() {
            Looper.prepare();
            //每个module都有接收消息处理ClientHandler
            mHandler = new ClientHandler();
            clientHandler = new Messenger(mHandler);
            if(resultRef!=null){
                try {
                    resultRef.set(clientHandler);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    //使用CountDownLatch唤醒机制保证线程安全
                    latch.countDown();
                }
            }
            Looper.loop();
        }

        public void quit() {
            mHandler.getLooper().quit();
        }
    }

12378910

2.绑定MessengerService作为进度间管理,并且绑定每一种模块的瑟维斯Connection

😉

/**
     * 连接服务器
     */
    public void connectService() {
        Intent intent = new Intent(MessengerService.class.getCanonicalName());// 5.0+ need explicit intent
        intent.setPackage(Constants.SERVICE_PACKAGE_NAME); // the package name of Remote Service
        //绑定MessengerService作为进程间管理,并且绑定每个模块的ServiceConnection
        boolean mIsBound = bindService(intent, mBaseModule.mConnection, BIND_AUTO_CREATE);
        LogUtils.i(Constants.TAG + " connectService", " ServiceConnection-->bindService  mIsBound: " + mIsBound);
    }

金沙国际官网 15

3.开发银行MessengerService,运营音讯循环

说起底要在顾客端加多相应的启航Service权限。

 @Override
    public void onCreate() {
        super.onCreate();
        LogUtils.i(Constants.TAG + " essengerService", "MessengerService -->onCreate");
        mWorkThread = new WorkThread();
        mWorkThread.start();
    }

    public class WorkThread extends Thread {
        public ServiceHandler mHandler;

        @Override
        public void run() {
            Looper.prepare();
            LogUtils.i(Constants.TAG + " essengerService", "MessengerService -->new ServiceHandler");
            //通过ServiceHandler来处理收到的消息
            mHandler = new ServiceHandler();
            Messenger mMessenger = new Messenger(mHandler);
          //  OkBus.getInstance().mServiceMessenger = mMessenger;
            try {
                resultRef.set(mMessenger);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                latch.countDown();
            }
            Looper.loop();
        }

        public void quit() {
            mHandler.getLooper().quit();
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        try {
            latch.await(10, TimeUnit.SECONDS); //最多等待10秒
        } catch (Exception e) { //等待中断
            e.printStackTrace();
        }
        Messenger mMessenger = resultRef.get();
        return mMessenger.getBinder();
    }

4.开首化OkBus并发送新闻注册

    public void initModule(BaseModule mBaseModule, Messenger mServiceMessenger, int mModuleId, Messenger mClientMessenger) {
        this.mServiceMessenger = mServiceMessenger;
        this.mModuleId = mModuleId;
        this.mBaseModule = mBaseModule;
        isModule.set(true);
        mBaseModule.isConnected.set(true);
        //线程池获取信息
        Message msg = Message.obtain();
        Bundle data = new Bundle();
        data.putInt(Constants.REGISTER_ID, mModuleId);//注册模块信息
        msg.setData(data);
        msg.replyTo = mClientMessenger;   //将处理消息的Messenger绑定到消息上带到服务端
        try {
            //发送到MessengerService中处理
            mServiceMessenger.send(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

5.ServiceHandler中保障叁个对Service Messenger到四个Client
Messenger的涉及

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        try {
            Bundle bundle = msg.getData();
            int registerId = bundle.getInt(Constants.REGISTER_ID, -1);
            if (registerId > 0) {//注册模块类型的消息
                LogUtils.logOnUI(Constants.TAG, "handleMessage: msg = [收到注册模块类型的消息]: registerId: " + Integer.toHexString(registerId));
                //每个模块对应的ClientHandler
                Messenger client = msg.replyTo; 
                mClientMessengers.put(registerId, client);//存储Client端接受处理消息的Messenger来发送Message到Client

                Message data = Message.obtain();
                Bundle mBundle = new Bundle();
                mBundle.putInt(Constants.REGISTER_RES, Constants.REGISTER_SEC);    //通知Client模块注册成功
                data.setData(mBundle);
                try {
                    client.send(data);  //回调注册状态给模块
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

6.介绍的模块注册结果

public class ClientHandler extends Handler {

    @Override
    public void handleMessage(Message msg) {
        ……
        int resCode = bundle.getInt(Constants.REGISTER_RES, -1);
        if (resCode < 0) {//收到普通消息
        ……
        } else {//收到模块注册结果消息
            boolean isRegisterSec = resCode == Constants.REGISTER_SEC;
            if (isRegisterSec) {
                LogUtils.logOnUI(Constants.TAG, "handleMessage() : reply = [注册成功]");
            }
        }
    }
}

7.其绑定落成之后,将module新闻登记到OkBus,之后会使用afterConneted()来开首化想要接收的信息

public ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            LogUtils.logOnUI(Constants.TAG, "ServiceConnection-->onServiceConnected 已自动唤醒服务器");
            Messenger mServiceMessenger = new Messenger(service);
            OkBus.getInstance().initModule(mBaseModule, mServiceMessenger, getModuleId(), mWorkThread.clientHandler);
            afterConnected();
        }

8.透过ServiceBus来注册别的module会跨module调用过来的新闻。

@Override
    public void afterConnected() {

        ServiceBus.getInstance().registerService(Constants.SERVICE_A_UID, msg -> {
            LogUtils.logOnUI(Constants.TAG, "afterConnected  a 进程收到[服务请求]消息:ServiceMessage-->hello:  " + Integer.toHexString(Math.abs(msg.what)));
            return "10086";
        });
    }

9.劳务注册后,能够看到其会通过onEvent重回回调的msg对象(CallBack接口)

    /**
     * 注册服务
     *
     * @param serviceId 服务id
     * @param callback  服务调用的回调
     * @param <T>       服务返回的数据范型
     */
    public <T> void registerService(final int serviceId, final CallBack<T> callback) {
        LogUtils.logOnUI(Constants.TAG, "注册服务  " + Integer.toHexString(Math.abs(serviceId)));
        okBus.unRegister(serviceId);//服务提供者只能有一个
        okBus.register(serviceId, msg -> {
            //TODO 优化到子线程
            okBus.onEvent(serviceId - 1, callback.onCall(msg));
        });
    }

到那边就介绍完开头化和登记流程了。

接下去介绍一下音信发送的架构,注意一下的模块服务法则

    //==================模块间的服务定义============//
    /**
     * 服务定义规则:
     * 1、服务的请求ID必须是负值(正值表示事件)
     * 2、服务的请求ID必须是奇数,偶数表示该服务的返回事件,
     * 即:   requestID-1 = returnID
     * 例如  -0xa001表示服务请求  -0xa002表示-0xa001的服务返回
     */
    public static final int SERVICE_A_UID = -0xa001;

        /**
         * 异步调用远端服务
         */
        findViewById(R.id.bt_1).setOnClickListener(v -> {
        //异步调用,
           ServiceBus.getInstance().fetchService(Constants.SERVICE_A_UID, msg -> {
                LogUtils.logOnUI(Constants.TAG, "b 进程收到[异步服务返回]消息:  获取到的UID-->" + msg.obj);
                Toast.makeText(BModuleActivity.this,
                        "b 进程收到[异步服务返回]消息:  获取到的UID-->" + msg.obj,
                        Toast.LENGTH_SHORT).show();
            });
        });

具体步骤
1.对ID的呼吁限制
2.module连接的判定,未有连接就尝试连接
3.提醒指标经过
4.报了名回调
5.文告指标模块

金沙国际官网 16

跨模块通讯

    /**
     * 异步调用服务
     *
     * @param serviceId 服务id
     * @param callback  回调
     */
    public void fetchService(final int serviceId, final Event callback) {
        if (serviceId > 0 || serviceId % 2 == 0) {
            assert false : "请求ID必须是负奇值!";
            return;
        }
        if (okBus.isModule() && !okBus.isModuleConnected()) {
            LogUtils.logOnUI(Constants.TAG, "请求失败,服务已经断开链接,尝试重新打开服务,进行请求");
            BaseAppModuleApp.getBaseApplication().connectService();
            return;
        }

        //自动唤醒目标进程
        if (okBus.isModule()) {
            String module_name = Integer.toHexString(Math.abs(serviceId)).substring(0, 1);
            noticeModule(module_name, serviceId, null);
        }

        //1、先注册回调
        okBus.register(serviceId - 1, msg -> {
            callback.call(msg);
            okBus.unRegister(serviceId - 1);//服务是单次调用,触发后即取消注册
        });
        //2、通知目标模块
        okBus.onEvent(serviceId);
    }

唤醒目的经过

    /**
     * 唤醒目标进程
     *
     * @param module_name 模块名
     * @param serviceId   服务ID
     * @param url         要打开的url
     */
    public void noticeModule(String module_name, int serviceId, String url) {
        Intent ait = new Intent(NoticeService.class.getCanonicalName());// 5.0+ need explicit intent        //唤醒目标进程的服务Action名
        ait.setPackage(Constants.MODULE_PACKAGE_PRE + module_name);   //唤醒目标进程的包名
        //绑定包名
        BaseAppModuleApp.getBaseApplication().bindService(ait, new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                if (service != null) {
                    LogUtils.logOnUI(Constants.TAG, "已经自动唤醒" + module_name);
                    Messenger moduleNameMessenger = new Messenger(service);
                    Message _msg = Message.obtain();
                    Bundle _data = new Bundle();
                    _data.putBoolean(Constants.NOTICE_MSG, true);
                    _msg.setData(_data);
                    _msg.replyTo = okBus.mServiceMessenger;//把服务器的信使给目标组件的信使,让他俩自己联系,这里仅仅是通知
                    try {
                        moduleNameMessenger.send(_msg);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    try {
                        Thread.sleep(200);//给服务器和目标组件500ms联系的时间
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                } else {
                    LogUtils.logOnUI(Constants.TAG, module_name + "进程,本来就是醒的");
                }

                if (serviceId < 0) {  //唤醒成功,继续发送异步请求,通知目标模块
                    okBus.onEvent(serviceId);
                }
                if (!TextUtils.isEmpty(url)) {  //目标url不为空,继续打开目标
                    OkBus.getInstance().onEvent(Constants.ROUTER_OPEN_URL, url);
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                LogUtils.logOnUI(Constants.TAG, "自动唤醒目标进程失败 module_name:" + module_name);
            }
        }, BIND_AUTO_CREATE);
    }

起步模块,并传递绑定对象

    /**
     * 收到唤醒通知之后,初始化模块,并自动去服务器注册
     *
     * @param intent
     * @return
     */
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        LogUtils.logOnUI(Constants.TAG, getPackageName() + " 收到唤醒通知");
        //获取模块的module
        BaseModule mBaseModule = BaseAppModuleApp.getBaseApplication().mBaseModule;
        if (!mBaseModule.isConnected.get()) {
            LogUtils.logOnUI(Constants.TAG, getPackageName() + " 我被唤醒啦");
            //初始化module,启动module的ClientHandler(Messenger)
            mBaseModule.init(latch, resultRef);
            mBaseModule.afterConnected();
            try {
                //超时限制
                latch.await(2000, TimeUnit.SECONDS);
            } catch (Exception e) { //等待中断
                e.printStackTrace();
            }
        }
        //返回ClientHandler的Binder对象
        return mBaseModule.mWorkThread.clientHandler.getBinder();
    }

出殡信息,其最终是经过瑟维斯Bus转载到各样模块OkBus,然后Binder传递的Messenger关联来成功新闻传递。

/**
     * @param tag  发送消息的事件ID
     * @param data 发送消息的数据
     * @return
     */
    public OkBus onEvent(int tag, Object data) {
        //发送时间,所以tag小于0
        String hex = Integer.toHexString(Math.abs(tag));
        LogUtils.i("Message OkBus", "onEvent  " + (tag > 0 ? "[普通]" : "[服务]") + "  tag: " + hex);

        //1、本地先处理非服务消息
        if (tag >= 0) onLocalEvent(tag, data);

        //2、如果是组建化,向服务器发消息
        if (isModule.get()) {
            //保证发送时服务启动
            if (!isModuleConnected()) {
                LogUtils.i("Message OkBus", "发消息失败,服务已经断开链接,尝试重新打开服务,进行发消息");
                BaseAppModuleApp.getBaseApplication().connectService();
                return this;
            }
           //数据为空,即为事件
            if (data == null || data instanceof Serializable) {
                Message newMsg = new Message();
                if (data != null) {
                    Bundle bundle = new Bundle();
                    bundle.putSerializable(Constants.MESSAGE_DATA, (Serializable) data);
                    newMsg.setData(bundle);
                }
                newMsg.arg1 = mModuleId;
                newMsg.what = tag;
                try {
                    //发送信息到目标Service
                    mServiceMessenger.send(newMsg);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                assert false : "跨进程时,你传递的对象没有序列化!";
            }
        } else if (tag < 0) {//非组件化时本地处理服务消息
            onLocalEvent(tag, data);
        }
        return this;
    }

应用Messenger通信框架设计就介绍到那边。
1.Modular框架,模块内传输使用了OkBus的路由传输,而在跨模块则选取Messenger的法子来实现
2.Messenger实际是一个封装好的IBinder对象
3.Modular透过成立设置跨模块的传输的情商逻辑来完毕消息传输

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图