Android 活动<;应用程序名称>;已泄漏ServiceConnection<;服务连接名称>@438030a8原订于此
我正在开发我的第一个Android应用程序。我的应用程序中有三个活动,用户频繁地来回切换。我还有一个远程服务,它处理telnet连接。应用程序需要绑定到此服务才能发送/接收telnet消息 编辑 感谢BDLS提供的信息丰富的答案。根据您对将Android 活动<;应用程序名称>;已泄漏ServiceConnection<;服务连接名称>@438030a8原订于此,android,serviceconnection,Android,Serviceconnection,我正在开发我的第一个Android应用程序。我的应用程序中有三个活动,用户频繁地来回切换。我还有一个远程服务,它处理telnet连接。应用程序需要绑定到此服务才能发送/接收telnet消息 编辑 感谢BDLS提供的信息丰富的答案。根据您对将bindService()作为独立函数使用或在startService()之后使用的区别的说明,我已经重新编写了我的代码,现在我只在使用后退按钮在活动之间循环时间歇性地收到泄漏错误消息 “我的连接”活动具有以下onCreate()和onDestroy(): 因
bindService()
作为独立函数使用或在startService()之后使用的区别的说明,我已经重新编写了我的代码,现在我只在使用后退按钮在活动之间循环时间歇性地收到泄漏错误消息
“我的连接”活动具有以下onCreate()
和onDestroy()
:
因此,服务在活动启动时启动,如果没有成功建立telnet连接,则在活动销毁时停止(connectStatus==0
)。其他活动仅在成功连接时绑定到服务(connectStatus==1
,保存到共享首选项)。这是他们的onResume()
和onDestroy()
:
因此,绑定发生在onResume()
中,因此它将从连接活动中获取已更改的状态,并且在onDestroy()
函数中,如果需要,它将解除绑定
结束编辑
但在切换活动时,我仍然会间歇性地收到内存泄漏错误消息“Activity has leaked ServiceConnection@438030a8,它最初绑定在这里”。我做错了什么
提前感谢您提供的任何提示和建议
完整错误消息如下(来自修订代码):
我想这可能与您所说的类似,当调用unbindService()
时,与服务的绑定没有完成,但是我尝试在服务上调用一个方法,因为我在每个活动中都进行了备份,以验证绑定是否完成,并且它们都很顺利
一般来说,这种行为似乎与我在每项活动中停留的时间无关。然而,一旦第一个活动泄漏了它的serviceConnection,它们都会按照我在那之后通过它们返回的方式进行操作
还有一件事,如果我在开发工具中打开“立即销毁活动”,它可以防止这个错误
有什么想法吗?您没有提供任何来自LightFactoryRemote
的代码,因此这只是一个假设,但如果您单独使用bindService
方法,您可能会遇到这种问题
要确保服务保持运行,即使在启动它的活动调用了其onDestroy
方法之后,也应首先使用startService
州的android文档:
使用startService()会覆盖由bindService(Intent,ServiceConnection,int)管理的默认服务生存期:它要求服务在调用stopService(Intent)之前保持运行,而不管是否有任何客户端连接到它
鉴于:
只要调用上下文存在,系统就会认为该服务是必需的。例如,如果此上下文是已停止的活动,则在该活动恢复之前,不需要继续运行服务
因此,所发生的是绑定(并因此启动)服务的活动已停止,因此系统认为不再需要该服务并导致该错误(然后可能停止该服务)
例子
在本例中,无论调用活动是否正在运行,服务都应保持运行
ComponentName myService = startService(new Intent(this, myClass.class));
bindService(new Intent(this, myClass.class), myServiceConn, BIND_AUTO_CREATE);
第一行启动服务,第二行将其绑定到活动。您提到的用户在活动之间切换非常快。是否在建立服务连接之前,您正在调用解除绑定服务
?这可能会导致无法解除绑定,然后泄漏绑定
不完全确定你如何处理这件事。。。如果调用了onServiceConnected
,您可以调用unbindService
,如果已经调用了onDestroy
。但我不确定这是否行得通
如果还没有,可以向服务中添加onUnbind方法。这样,您可以准确地看到类何时从中解除绑定,这可能有助于调试
@Override
public boolean onUnbind(Intent intent) {
Log.d(this.getClass().getName(), "UNBIND");
return true;
}
您可以在恢复时绑定,但在恢复时解除绑定。您应该在onPause
中执行解除绑定,以便始终存在匹配的绑定/解除绑定调用对。间歇性错误将出现在活动暂停但未销毁,然后再次恢复的位置。尝试在OnUserLeaveHint()中使用unbindService()。它可以防止ServiceConnection泄漏场景和其他异常。
我在代码中使用了它,效果很好。您只需在onDestroy()
中解除服务绑定即可。然后,警告就会消失
看
正如活动文档试图解释的那样,有三个主要绑定/取消绑定
您将使用的分组:onCreate()和onDestroy()、onStart()和
onStop()、onResume()和onPause()
活动中绑定的每个服务必须在应用程序关闭时解除绑定
所以试着使用
onPause(){
unbindService(YOUR_SERVICE);
super.onPause();
}
您可以使用:
@Override
public void onDestroy() {
super.onDestroy();
if (mServiceConn != null) {
unbindService(mServiceConn);
}
}
您可以使用布尔值来控制它,所以只有在进行绑定时才调用unbind
public void doBindService()
{
if (!mIsBound)
{
bindService(new Intent(this, DMusic.class), Scon, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
}
public void doUnbindService()
{
if (mIsBound)
{
unbindService(Scon);
mIsBound = false;
}
}
如果您只想在它已连接的情况下解除绑定
public ServiceConnection Scon = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder binder)
{
mServ = ((DMusic.ServiceBinder) binder).getService();
mIsBound = true;
}
public void onServiceDisconnected(ComponentName name)
{
mServ = null;
}
};
我最近一直在阅读有关Android服务的文章,并有机会深入了解它。我遇到了一个服务泄漏,就我的情况而言,它的发生是因为我有一个未绑定的服务,该服务正在启动一个绑定的服务,但在此情况下,我的未绑定的服务被一个活动所取代
onPause(){
unbindService(YOUR_SERVICE);
super.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
if (mServiceConn != null) {
unbindService(mServiceConn);
}
}
public void doBindService()
{
if (!mIsBound)
{
bindService(new Intent(this, DMusic.class), Scon, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
}
public void doUnbindService()
{
if (mIsBound)
{
unbindService(Scon);
mIsBound = false;
}
}
public ServiceConnection Scon = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder binder)
{
mServ = ((DMusic.ServiceBinder) binder).getService();
mIsBound = true;
}
public void onServiceDisconnected(ComponentName name)
{
mServ = null;
}
};
public void onServiceConnected(ComponentName name, IBinder service) {
bounded = true;
// code here
}
public void onServiceDisconnected(ComponentName name) {
bounded = false;
}
private final ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// your work here.
serviceBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
serviceBound = false;
}
if (serviceBound) {
unbindService(serviceConnection);
}