Messenger源码分析

Messenger 简介

Messenger(信使) 是一种跨进程通信实现方式,是对 AIDL 的进一步封装,省去了两端创建 AIDL 的过程。

Messenger 用例

服务端

// MessengerRemoteService.java
public class MessengerRemoteService extends Service {
    // 服务端 Messenger
    private final Messenger serviceMessenger = new Messenger(new MessageHandler());
    
    static class MessageHandler extends Handler {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            // 客户端 Messenger
            Messenger clientMessenger = msg.replyTo;
            if (clientMessenger == null) {
            	return;
        	}
            // 向客户端回复消息
            try {
            	Message message = Message.obtain();
            	Bundle data = new Bundle();
                data.putString("msg", "服务端回复收到来自客户端的消息");
            	message.setData(data);
            	clientMessenger.send(message);
        	} catch (RemoteException e) {
            	e.printStackTrace();
        	}
        }
    }
    
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return serviceMessenger.getBinder();
    }
}
<!--AndroidManifest.xml-->
<service
    android:name=".MessengerRemoteService"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="com.example.demo.MessengerRemoteService" />
    </intent-filter>
</service>
startService(new Intent(this, MessengerRemoteService.class));

客户端

Intent intent1 = new Intent();
intent1.setPackage("com.example.demo");
intent1.setAction("com.example.demo.MessengerRemoteService");
bindService(intent1, new MessengerServiceConnection(), Service.BIND_AUTO_CREATE);
// 客户端 Handler
static class MessengerClientHandler extends Handler {
    @Override
    public void handleMessage(@NonNull Message msg) {
        super.handleMessage(msg);
    }
}

static class MessengerServiceConnection implements ServiceConnection {
    // 客户端 Messenger
    private final Messenger clientMessenger = new Messenger(new MessengerClientHandler());
    // 服务端 Messenger
    private Messenger serviceMessenger;

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        serviceMessenger = new Messenger(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
    }

    public void send() {
        if (serviceMessenger == null) {
            return;
        }
        try {
            Message message = Message.obtain();
            Bundle data = new Bundle();
            message.setData(data);
            message.replyTo = clientMessenger;
            serviceMessenger.send(message);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

源码解析

首先看一下服务端代码,服务端的 onBind() 方法中创建了一个 服务端Messenger ,传入一个服务端的Handler,然后调用 Messenger 的 getBinder() 方法返回了一个 IBinder。

// Messenger.java
private final IMessenger mTarget;
public Messenger(Handler target) {
    mTarget = target.getIMessenger();
}

public IBinder getBinder() {
    return mTarget.asBinder();
}

构造方法中调用了服务端Handler 的 getIMessenger() 方法,获取了一个IMessenger并保存到mTarget。从这里看出 Messager 实际上就是这个 mTarget 的一个代理类。

// Handler.java
@UnsupportedAppUsage
final IMessenger getIMessenger() {
    synchronized (mQueue) {
        if (mMessenger != null) {
            return mMessenger;
        }
        mMessenger = new MessengerImpl();
        return mMessenger;
    }
}

getIMessenger() 方法是获取一个 MessengerImpl 单例。

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

MessengerImpl 是 Handler 内置的一个 IMessenger.Stub 实现类。send() 方法就是调用服务端 Handler 的 sendMessage() 方法。等等…Stub 是不是非常熟悉?这个其实就是AIDL为我们生成的 Stub,IMessenger 就是Android为我们定义的AIDL接口。

// IMessenger.aidl
import android.os.Message;
oneway interface IMessenger {
    void send(in Message msg);
}

下面看一下客户端代码,客户端连接成功后调用也是创建了一个Messenger,但是传入的不是Handler,而是IBinder。

public Messenger(IBinder target) {
    mTarget = IMessenger.Stub.asInterface(target);
}
public void send(Message message) throws RemoteException {
    mTarget.send(message);
}

这里的逻辑非常简单,就是利用 AIDL 调用服务端的send()方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值