我们使用Handler都是在一个进程中使用的,如何跨进程使用Handler?
其实这个问题不难解决,自己动手对binder进行一些封装就可以简单实现。但是当你看系统源码,就会发现,其实这些android都已经为我们做好了。
使用android系统的android.os.Messenger可以很方便的跨进程使用Handler。下面是示例程序。
首先是服务端。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public
class
MessengerTestService
extends
Service {
protected
static
final
String TAG =
"MessengerTestService"
;
private
Handler mHandler =
new
Handler() {
@Override
public
void
handleMessage(Message msg) {
switch
(msg.what) {
case
1
:
Log.d(TAG,
"收到消息"
);
//获取客户端message中的Messenger,用于回调
final
Messenger callback = msg.replyTo;
try
{
// 回调
callback.send(Message.obtain(
null
,
0
));
}
catch
(RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break
;
}
}
};
@Override
public
IBinder onBind(Intent intent) {
return
new
Messenger(mHandler).getBinder();
}
}
|
然后是客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
public
class
MainActivity
extends
Activity {
protected
static
final
String TAG =
"MainActivity"
;
Messenger messenger;
Messenger reply;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
reply =
new
Messenger(handler);
Intent intent =
new
Intent();
intent.setClassName(
"test.messenger"
,
"test.messenger.MessengerTestService"
);
// 绑定服务
bindService(intent,
new
ServiceConnection() {
@Override
public
void
onServiceDisconnected(ComponentName name) {
}
@Override
public
void
onServiceConnected(ComponentName name, IBinder service) {
Toast.makeText(MainActivity.
this
,
"bind success"
,
0
).show();
messenger =
new
Messenger(service);
}
}, Context.BIND_AUTO_CREATE);
}
public
void
sendMessage(View v) {
Message msg = Message.obtain(
null
,
1
);
// 设置回调用的Messenger
msg.replyTo = reply;
try
{
messenger.send(msg);
}
catch
(RemoteException e) {
e.printStackTrace();
}
}
private
Handler handler =
new
Handler() {
@Override
public
void
handleMessage(Message msg) {
Log.d(TAG,
"回调成功"
);
}
};
}
|
客户端绑定服务端,获取远程Messenger的binder对象。调用Messenger的send函数,就可以吧Message发送至服务端的Handler。
同时,如果需要服务端回调客户端(往客户端的Handler发消息),则可以在send的Message中设置replyTo,服务端就可以往客户端发送消息了。
下面我们看下Messenger的源码,还是很简单的。
构造函数
1
2
3
|
public
Messenger(Handler target) {
mTarget = target.getIMessenger();
}
|
Handler.getIMessenger()返回的是一个IMessenger的binder对象,它的send方法将会调用Handler的sendMessage方法。
1
2
3
|
public
void
send(Message message)
throws
RemoteException {
mTarget.send(message);
}
|