Android进程间的通信之Messenger

Android AIDL和Messenger区别

使用Messenger是执行进程间通信最简单的方法,因为Messenger会在单一线程中创建包含所有请求的队列,这样您就不必对服务进行线程安全设计。而纯粹的AIDL接口会同时向服务发送多个请求,服务随后必须应对多线程处理。

AIDL通常应用在服务被设计到单独的应用中的场景(即服务端可客户端不属于同一个app的情况),而Messenger通常应用在同一app的不同进程的场景中。

Messenger基本思想

服务端(被动方)提供一个Service来处理客户端(主动方)连接,维护一个Handler(具体来讲:是Handler的子类)来创建Messenger,在onBind时返回Messenger的binder(调用Messenger的getBinder()方法,该方法返回一个IBinder对象,客户端将通过该对象作为参数创建一个Messenger对象用于与服务端进行通信)。

Messenger使用步骤

1、服务端实现一个Handler,由其接收来自客户端的每个调用的回调
2、使用第1步的Handler的实例作为target创建Messenger对象(即该Messenger持有了对Handler的引用)
3、使用Messenger创建一个IBinder(通过调用Messenger的getBinder()方法),服务端的onBind()方法中将其返回到客户端
4、客户端使用IBinder将Messenger(引用服务端的Handler实例)实例化,然后使用后者将Message对象发送给服务端
5、服务端在其Handler中接收每个Message

这样,客户端并没有调用服务端的“方法”,而客户端传递的消息(Message对象)是服务端在其Handler中接收到的。

如果想让服务端对客户端发回响应,则还需要在客户端中创建一个持有客户端Handler实现类的Messenger,当客户端收到onServiceConnected()回调时,在向服务发送的Message时,send()方法的replyTo参数中需包含客户端的Messenger。这样,客户端就可在其Handler实现类中接收到来自服务端的响应消息。

简单示例

AndroidMainfest.xml

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="yf.exam.client.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service android:name=".MessengerService" android:process=":custom_process"/>
</application>

布局文件很简单,这里只有一个按钮,用于向服务端发送消息并显示服务端响应内容,这里不再给出。

客户端:MainActivity

public class MainActivity extends Activity {
    private static final int REPLY_MSG_ID = 2;
    private boolean mServiceConnected = false;
    private Button btn = null;
    //用于向Service端发送消息的Messenger
    private Messenger mBoundServiceMessenger = null;
    //用于接收Service发送消息的Messenger
    private final Messenger mReceiveMessenger = new Messenger(new ReceiveMessHandler(this));
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mBoundServiceMessenger = null;
            mServiceConnected = false;
        }
        
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBoundServiceMessenger = new Messenger(service);
            mServiceConnected = true;
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = (Button)findViewById(R.id.button);
        bindService(new Intent(this, MessengerService.class), conn, Context.BIND_AUTO_CREATE);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mServiceConnected){
                    //获取消息对象
                    Message msg = Message.obtain(null, 1, 0, 0);
                    try{
                        //replyTo参数包含客户端Messenger
                        msg.replyTo = mReceiveMessenger;
                        //向Service端发送消息
                        mBoundServiceMessenger.send(msg);
                    }catch(RemoteException re){
                        re.printStackTrace();
                    }
                }
            }
        });
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(mServiceConnected){
            unbindService(conn);
            mServiceConnected = false;
        }
    }
    /**
     * 客户端实现一个Handler用于接收服务端返回的响应
     * @author Administrator
     *
     */
    static class ReceiveMessHandler extends Handler{
        //持有当前Activity的弱引用,避免内存泄露
        private final WeakReference<MainActivity> mActivity;
        public ReceiveMessHandler(MainActivity activity){
            mActivity = new WeakReference<MainActivity>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what){
            case REPLY_MSG_ID:
                Toast.makeText(mActivity.get(), msg.getData().getString("msg"), Toast.LENGTH_SHORT).show();
                break;
            }
        }
    }
}

服务端:MessengerService.java

public class MessengerService extends Service {
    private static final int REPLY_MSG_ID = 2;
    private static final int MSG_ID = 1;
    static class BoundServiceHandler extends Handler{
        private final WeakReference<MessengerService> mService;
        public BoundServiceHandler(MessengerService service){
            mService = new WeakReference<MessengerService>(service);
        }
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what){
            case MSG_ID:
                Messenger replyMessenger = msg.replyTo;
                Message replyMsg = Message.obtain(null, REPLY_MSG_ID);
                //向客户端响应的消息内容
                Bundle b = new Bundle();
                b.putString("msg", "this is the message reply from service");
                replyMsg.setData(b);
                try{
                    replyMessenger.send(replyMsg);
                }catch(RemoteException re){
                    re.printStackTrace();
                }
                break;
                default:
                    super.handleMessage(msg);
            }
        }
    }
    private final Messenger mMessenger = new Messenger(new BoundServiceHandler(this));
    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
        return mMessenger.getBinder();
    }
}

此外,上述例子中所有的Handler的实现类都被声明为static并使用Service或Activity的WeakReference。如果不这样做,编译器会给出警告信息“This handler class should be static or leaks might occur”。通过使用弱引用的方式,就允许Service或Activity进行垃圾收集了。

 

Android进程间的通信之Messenger

上一篇:iOS UI(布局)约束是什么?view1.attr1 = view2.attr2 * multiplier + constant


下一篇:关于win10安卓真机调试无法找到设备的问题