【发布时间】:2012-08-30 20:11:50
【问题描述】:
我有一个应用程序使用Messenger 接口与远程进程中的Service 通信。以下是事物设置的基本架构:
- 应用程序生成多个需要访问服务的“操作”对象。
- 每个“操作”都包含一个包裹在
Messenger中的Handler,用于接收来自Service的响应数据 - 当操作执行时,它将其
Messenger包装成Intent并调用startService()将消息传递给远程服务 - 远程服务根据
Intent的参数执行一些工作,然后通过向Messenger发送Message来返回响应以执行该操作。
以下是操作中的基本代码:
public class SessionOperation {
/* ... */
public void runOperation() {
Intent serviceIntent = new Intent(SERVICE_ACTION);
/* Add some other extras specific to each operation */
serviceIntent.putExtra(Intent.EXTRA_EMAIL, replyMessenger);
context.startService(serviceIntent);
}
private Handler mAckHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//Process the service's response
}
};
protected Messenger replyMessenger = new Messenger(mAckHandler);
}
以及服务的结构(基本上是一个IntentService,当队列为空时不会关闭):
public class WorkService extends Service {
private ServiceHandler mServiceHandler;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//If intent has a message, queue it up
Message msg = mServiceHandler.obtainMessage();
msg.obj = intent;
mServiceHandler.sendMessage(msg);
return START_STICKY;
}
private void onHandleIntent(Intent intent) {
Messenger replyTarget = intent.getParcelableExtra(Intent.EXTRA_EMAIL);
/* Do some work */
Message delivery = Message.obtain(...);
replyTarget.send(delivery);
}
}
这一切都非常好。我可以将来自多个不同应用程序的大量操作发送到同一个服务,它们都会处理并将响应发送到正确的位置。不过……
我注意到,如果应用程序运行的时间足够长并且有足够的活动,它会以OutOfMemoryError 崩溃。在查看 MAT 中的 HPROF 数据时,我注意到所有这些操作都保留在内存中,并且由于 Messenger 而被垃圾收集器扣为人质。显然,Messenger 实例正在创建一个与 Binder 的长期本机连接,该连接算作 GC Root,它将每个“操作”对象无限期地保存在内存中。
有谁知道是否有办法在“操作”结束时清除或禁用Messenger,以免造成这种内存泄漏?是否有另一种方法可以以相同的方式将 IPC 实现到 Service,以便多个不同的对象可以发出请求并异步获取结果?
提前致谢!
【问题讨论】:
标签: android service memory-leaks