正如标题所说,我正在寻找一种优雅的方式来实现 Android 中线程之间的通用异步请求/响应机制。
我需要能够:
- 使用不同类型的参数异步向另一个对象发送请求
- 通过将响应发布到发送者的队列,让该对象可选择地异步响应
假设我有扩展线程的管理器类型的对象。每个这样的 Manager 都有一个 Handler 和一个 Looper,这样它们就可以异步地将消息推送到彼此的队列中。
简单地说,在伪代码中,我会像这样实现它:
Manager extends Thread
{
// loop forever, pulling a request from the queue and handling it
listenToRequests()
{
Looper.prepare()
m_handler = new Handler()
{
handleMessage(msg)
{
switch(msg.what)
{
case REQUEST_TYPE_0:
handleRequestType0(msg.object, msg.args);
break;
case REQUEST_TYPE_1:
handleRequestType1(msg.object, msg.args);
break;
...
}
}
}
}
其他管理器实例需要分配一条消息,填充它并将其发送到目标管理器:
msg = targetManager.getHandler().obtainMessage();
msg.what = REQUEST_TYPE_0;
msg.object = this;
msg.args = ...;
msg.sendToTarget();
然后目标管理器可以在发送者上获取Message(),填充响应消息并发送它。
上面代码的问题在于,虽然它确实满足了这两个要求,但对于每条消息都有很多烦人的样板代码需要实现:
- 在某些枚举中定义消息类型(例如 REQUEST_TYPE_N)
- 将大量参数放入消息中,以便对它们进行编组
- 添加一个 switch case 来调度消息并处理它
使用 Runnable 确实解决了打包参数和消除消息调度的问题(通过 switch/case):
public void doRequest0(args)
{
handler.post(new Runnable()
{
@Override
public void run()
{
// do stuff with args...
args.sender.request0Response(...);
}
});
}
这样做的问题是,代替回调,我必须声明和实现响应接口。在每个这样的接口函数中,我都必须用 handler.post(new Runnable() ... 进行装饰,这似乎也是很多样板代码。
我还有其他选择吗?看起来我的要求很谦虚,但我的解决方案在语法上过于复杂。