当Activity关闭并重新打开时避免服务回调
我有一个LocalService,它公开了一些Binder与一些API。我创建了一个服务侦听器,就像这样:当Activity关闭并重新打开时避免服务回调
if (dataServiceListener == null) {
dataServiceListener = new DataServiceListener();
mainActivity.getApplicationContext().bindService
(new Intent(mainActivity, LocalService.class),
dataServiceListener.svcConn, mainActivity.BIND_AUTO_CREATE);
}
后,我打电话了Binder
在dataServiceListener
自曝,我得到的dataServiceListener
onResult()
方法的响应方法。到目前为止,没有一种问题,一切都在起作用。 当我关闭正在等待服务侦听器回调的活动并立即重新打开时,会发生某种问题。尽管我重新实例化dataServiceListener
onCreate()
,我得到两个回调,而不是一个,旧的来自被销毁的Activity和后者(右)。这种方式将结果混合在用户界面上。 有没有办法告诉服务或服务监听器,当活动结束时,必须避免回调。或者甚至可能销毁ServiceListener对象。
我觉得这是马克·L.·墨菲(Commonsware)中所描述的“忙编码器的指南Android的发展”的问题:
最大的缺点是,以确保活动缩回听众时它完成了。
我该怎么做?当活动结束时,有没有办法摆脱无用的听众?
谢谢!
我终于解决了这个问题(也没有,我没有这么长时间的工作:D)。
在调用Fragment
的onDestroy
之前,向听众回叫。所以布尔型“dontupdate”值从未设置为false。在主要活动中重写onBackPressed
解决了问题,因为我为每个片段调用了一个destroy()
方法,该方法负责将布尔值设置为false。
我也有这个问题。您需要在服务完成时释放服务中的所有资源,侦听器,线程。
你的活动必须注册/注销自己作为监听器。您需要使用正确的生命周期回调方法,而不是onBackPressed()
。注册onStart()
,取消注册onStop()
。一种方法是让侦听器成为服务的静态成员,并提供静态注册/取消注册方法。然后根据您的活动进行适当的调用。
您显示的代码是用于绑定到服务的。您不会显示您正在向该服务注册侦听器的位置。您显然是基于您的问题和您对onResult()
方法的参考。鉴于你的问题的性质,我要猜你正在做的是:
- 绑定到服务
onCreate()
- 在
onServiceConnected()
,你正在呼吁Binder
某种
setListener()
方法
在这种情况下,如果我们忽略配置更改,放松问题的正确方法是,在onDestroy()
,呼吁Binder
一些removeListener()
方法,然后调用unbindService()
。
配置变化,特别是在一个前碎片世界,使这变得复杂。这就是为什么this sample project(以及the book中附带的材料)太过恶劣的原因。绑定是棘手的 - 如果您从旧活动中解除绑定,并且没有任何其他服务保持服务,则在新活动有机会绑定之前,服务将关闭。绑定也是国家 - 你不能简单地解除绑定,以免泄漏东西。
所以,配方变为:使用Application
Context
onServiceConnected()
,调用排序在Binder
onRetainNonConfigurationInstance()
setListener()
方法
- 绑定到服务中
onCreate()
,记的事实上,您正在进行配置更改,并返回一些Object
,其中包含您的Binder
,您的Listener
以及您所有州的所有其他人 - 在
onCreate()
,使用getLastNonConfigurationInstance()
- 如果它是null
,继续正常的,但如果它不是null
,守住那Binder
和Listener
,不重新绑定并重新注册听众 - 在
onDestroy()
,如果上述步骤#3的标记是false
(即,我们是而不是正在进行配置更改),请拨打Binder
上的removeListener()
方法,然后拨打unbindService()
。
使用与setRetainInstance(true)
片段可能可以简化这一些,虽然我还没有通过一个样本。
我就是这么做的。 基本上,我有一个活动与多个片段。每个片段可以有一个或多个服务绑定,因为它可能需要同时执行多个任务。 在主要活动的'onBackPressed()'中,我通过'boolean'值将所有服务侦听器设置为某种非工作状态。然后我完成活动。但是这并不如预期的那样工作:如果我为'onBackPressed()'方法设置了断点,它肯定会起作用,但出于某种原因,没有断点,'onResult()'方法在'onBackPressed )'! – frapontillo
@MacGyver:“我做到了。” - 好吧,你的描述似乎不匹配。例如,你会注意到我没有提到'onBackPressed()',部分原因是因为这个不足。 “每个片段可以有一个或多个服务绑定,因为它可能需要同时执行多个任务。” - 你不应该需要多个绑定。你只需要一个服务,因此一个'Binder'。 – CommonsWare
好的,在所述片段的onDestroy()我现在有: 'dataServiceListener.serviceBinder.removeListener();' 'getActivity()getApplicationContext()unbindService(dataServiceListener.svcConn);' 然而,这并未。什么都不会改变。 'removeListener()'只是在'ServiceBinder'中执行'listener = null'。 – frapontillo
我有同样的问题。我正在使用AIDL进行远程服务。当我尝试在foreach循环中使用ArrayList Collection中的remove方法取消注册我的监听器时,我遇到了这个问题,因为我没有在比较中使用asBinder。通过搜索解决方案,我找到了Android API中的RemoteCallbackList类。这个课程正是我所需要的,我认为你应该做的,在一个简单的方法,采取所有reponsabilites艰苦的工作,涉及这项任务。
从Android API:
要使用这个类,只需用你的服务一起创建一个实例,并调用它的寄存器(E)和注销(E)的方法为客户寄存器,并注销您的服务。要回叫已注册的客户端,请使用beginBroadcast(),getBroadcastItem(int)和finishBroadcast()。
广播样本:
int i = callbacks.beginBroadcast();
while (i > 0) {
i--;
try {
callbacks.getBroadcastItem(i).somethingHappened();
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing
// the dead object for us.
}
}
callbacks.finishBroadcast();
我怎样才能做到这一点?我只需要在Activity关闭后立即销毁我的监听器('onBackPressed()') – frapontillo
是的,你可以在那里完成你的活动并确保它完成,你也可以重写“onDestroy()”方法服务.. –
我的确如此,但它看起来就像onDestroy方法在onResult之后被调用,所以没有任何变化! – frapontillo