messenger android 4.,AndroidIPC机制(4)-Messenger
一、概述
除了使用 AIDL 進行 IPC 外,我們還可以使用 Messenger 來替代 AIDL。通過在 Message 對象中放入需要傳遞的對象,利用 Messenger 在不同進程間傳遞 Message 對象,就可以方便地進行進程間通信了
Messenger 是一種輕量級的 IPC 方案,底層實現依然是 AIDL,通過 Messenger 的兩個構造方法就可以看出來
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
Messenger 對 AIDL 進行了封裝,使開發者可以更簡單地進行進程間通信。此外,由于 Messenger 一次只處理一個請求,不會出現并發執行的問題,因此在服務端不用考慮進行線程同步
這里通過 Messenger 來實現一個簡單的進程間通信,客戶端發送一個整數給服務端,服務端再把這個數值打印出來
二、服務端
與 AIDL 一樣,服務端也要創建一個 Service 來處理客戶端的連接請求,但服務端的代碼要簡單得多
首先,通過一個 Handler 對象來創建 Messenger 對象,然后在 onBind 方法中返回 Messenger 對象底層的 Binder 即可
/**
* 作者:葉應是葉
* 時間:2018/3/22 20:13
* 描述:https://github.com/leavesC
*/
public class MessengerService extends Service {
private static final String TAG = "MessengerService";
private static final int CODE_MESSAGE = 1;
private static class MessengerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case CODE_MESSAGE: {
Log.e(TAG, "服務端收到了消息:" + msg.arg1);
break;
}
}
}
}
private Messenger messenger = new Messenger(new MessengerHandler());
public MessengerService() {
}
@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
}
三、客戶端
客戶端首先要綁定服務端的 Service,綁定成功后通過 ServiceConnection 對象的 onServiceConnected 方法的參數 IBinder 來構造一個 Messenger 對象,之后通過 Messenger 對象即可向服務端發送消息了
/**
* 作者:葉應是葉
* 時間:2018/3/22 20:13
* 描述:https://github.com/leavesC
*/
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final int CODE_MESSAGE = 1;
private Messenger messenger;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
messenger = new Messenger(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
messenger = null;
}
};
private EditText et_message;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService();
initView();
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(serviceConnection);
}
private void bindService() {
Intent intent = new Intent();
intent.setClassName("com.czy.messenger_server", "com.czy.messenger_server.MessengerService");
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
private void initView() {
et_message = findViewById(R.id.et_message);
Button btn_sendMessage = findViewById(R.id.btn_sendMessage);
btn_sendMessage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (messenger == null) {
return;
}
String content = et_message.getText().toString();
if (TextUtils.isEmpty(content)) {
return;
}
int arg1 = Integer.valueOf(content);
Message message = new Message();
message.what = CODE_MESSAGE;
message.arg1 = arg1;
try {
messenger.send(message);
Log.e(TAG, "消息發送成功");
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
}
運行結果如下所示
在上面的示例代碼中我是用 Message 來承載需要發送的消息的,因為 Messenger 和 Message 都實現了 Parcelable 接口,所以可以跨進程傳輸。Message 中能用來承載數據的載體有 what、arg1、arg2、obj、Bundle、replyTo。當中,obj 字段在跨進程通信中只能用來承載系統提供的實現了 Parcelable 接口的對象,例如 Bundle 和 Intent。如果承載了非法數據(例如 String),則會發生運行時異常
四、雙向通信
以上的例子只是實現了單向通信,還要考慮下如何實現雙向通信,即服務端如何向客戶端反饋數據?這就需要客戶端也需要通過 Handler 創建一個 Messenger 對象,并將該 Messenger 對象通過 Message 的 replyTo 參數傳遞給服務端,服務端取得該參數就可以回應客戶端了
這里就直接修改上述 IPC 流程,將客戶端發給服務端的 arg1 參數乘以 2 后再返回給客戶端
首先修改服務端代碼
private static class MessengerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case CODE_MESSAGE: {
Log.e(TAG, "服務端收到了消息:" + msg.arg1 + " " + ((Intent) msg.obj).getAction());
//取得客戶端的 Messenger 對象
Messenger messenger = msg.replyTo;
Message message = new Message();
message.what = CODE_MESSAGE;
message.arg1 = 2 * msg.arg1;
try {
messenger.send(message);
Log.e(TAG, "服務端回復消息成功");
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
}
}
為了接收服務端的回復,客戶端也需要通過 Handler 創建一個 Messenger 對象,并將該 Messenger 對象通過 Message 的 replyTo 參數傳遞給服務端
private Messenger replyMessenger;
private static class MessengerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case CODE_MESSAGE: {
Log.e(TAG, "客戶端收到了服務端回復的消息:" + msg.arg1);
break;
}
}
}
}
btn_sendMessage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (messenger == null) {
return;
}
String content = et_message.getText().toString();
if (TextUtils.isEmpty(content)) {
return;
}
int arg1 = Integer.valueOf(content);
Intent intent = new Intent("Action");
Message message = new Message();
message.what = CODE_MESSAGE;
message.arg1 = arg1;
message.obj = intent;
//雙向通信時需要加上這一句
message.replyTo = replyMessenger;
try {
messenger.send(message);
Log.e(TAG, "消息發送成功");
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
運行結果如下所示
從以上介紹可以看出來,Messenger 的使用要比 AIDL 簡單得多,因為 Messenger 對 AIDL 進行了封裝,使之更加容易使用。但需要注意的是,Messenger 是以串行的方式處理客戶端發送的消息,即使有大量的消息同時到達服務端,服務端也只能一個個處理,所以 Messenger 不適合用于處理大量的并發請求,此時就還是需要考慮使用 AIDL 了,因為 AIDL 支持并發通信
這里提供本系列文章所有的 IPC 示例代碼:IPCSamples
總結
以上是生活随笔為你收集整理的messenger android 4.,AndroidIPC机制(4)-Messenger的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 缓存文件的工具类,总结的
- 下一篇: android 音视频 教程,Andro