我正在开发我的第一款Android应用。我的应用程序中有三个活动,用户来回切换频繁。我还有一个远程服务,它处理一个telnet连接。应用程序需要绑定到此服务才能发送/接收telnet消息。
修改
感谢BDLS提供的信息。我根据您对使用bindService()
作为独立函数或startService()
之间的区别的说明重新编写了代码,现在我只是在使用后面时间歇性地获取泄漏错误消息按钮在活动之间循环。
我的关联活动包含以下onCreate()
和onDestroy()
:
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*
* Initialize the ServiceConnection. Note that this is the only place startService() is run.
* It is also the only time bindService is run without dependency on connectStatus.
*/
conn = new TelnetServiceConnection();
//start the service which handles telnet
Intent i = new Intent();
i.setClassName( "com.wingedvictorydesign.LightfactoryRemote", "com.wingedvictorydesign.LightfactoryRemote.TelnetService" );
startService(i);
//bind to the service
bindService(i, conn, 0);
setContentView(R.layout.connect);
setupConnectUI();
}//end OnCreate()
@Override
protected void onDestroy() {
super.onDestroy();
//unbind the service and null it out
if (conn != null) {
unbindService(conn);
conn = null;
}
if(connectStatus == 0) {
//stop the service
Intent i = new Intent();
i.setClassName( "com.wingedvictorydesign.LightfactoryRemote", "com.wingedvictorydesign.LightfactoryRemote.TelnetService" );
stopService(i);
Log.d("LightfactoryRemote", "Connect onDestroy() attempted to stop service");
}
Log.d("LightfactoryRemote", "Connect onDestroy()");
}//end onDestroy()
因此,服务在活动启动时启动,如果没有成功的telnet连接(connectStatus == 0
),则在活动被销毁时停止。仅当成功建立连接(connectStatus == 1
,保存到共享首选项)时,其他活动才会绑定到服务。这是他们的onResume()
和onDestroy()
:
@Override
protected void onResume() {
super.onResume();
//retrieve the shared preferences file, and grab the connectionStatus out of it.
SharedPreferences settings = getSharedPreferences(PREFS_NAME, MODE_WORLD_WRITEABLE);
connectStatus = settings.getInt("connectStatus", 0);
Log.d("LightfactoryRemote", "Focus onResume with " + connectStatus);
//if a telnet connection is active, start the service and bind to it
if (connectStatus == 1) {
conn = new TelnetServiceConnection();
Intent i = new Intent();
i.setClassName("com.wingedvictorydesign.LightfactoryRemote", "com.wingedvictorydesign.LightfactoryRemote.TelnetService");
bindService(i, conn, 0);
//TODO write restore texview code
}//end if
}//end onResume
@Override
protected void onDestroy() {
super.onDestroy();
//unbind the service and null it out.
if (conn != null) {
Log.d("LightfactoryRemote", "Focus onDestroy() attempted to unbind service");
unbindService(conn);
conn = null;
}
Log.d("LightfactoryRemote", "Focus onDestroy()");
}//end onDestroy()
因此绑定发生在onResume()
中,以便它将从连接活动中获取更改的状态,并且在onDestroy()
函数中,如果需要,它将被解除绑定。
结束编辑
但在切换活动时,我仍然会间歇性地获取内存泄漏错误消息“Activity已泄漏最初绑定的ServiceConnection @ 438030a8”。我做错了什么?
提前感谢任何提示或指示!
完整的错误消息(来自修订后的代码):
01-02 22:04:26.642: DEBUG/LightfactoryRemote(2024): Focus onStop()
01-02 22:04:26.642: DEBUG/LightfactoryRemote(2024): Focus onDestroy() attempted to unbind service
01-02 22:04:26.642: DEBUG/LightfactoryRemote(2024): Focus onDestroy()
01-02 22:04:26.672: ERROR/ActivityThread(2024): Activity com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote has leaked ServiceConnection com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote$TelnetServiceConnection@439e51e8 that was originally bound here
01-02 22:04:26.672: ERROR/ActivityThread(2024): android.app.ServiceConnectionLeaked: Activity com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote has leaked ServiceConnection com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote$TelnetServiceConnection@439e51e8 that was originally bound here
01-02 22:04:26.672: ERROR/ActivityThread(2024): at android.app.ActivityThread$PackageInfo$ServiceDispatcher.<init>(ActivityThread.java:927)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at android.app.ActivityThread$PackageInfo.getServiceDispatcher(ActivityThread.java:822)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at android.app.ApplicationContext.bindService(ApplicationContext.java:842)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at android.content.ContextWrapper.bindService(ContextWrapper.java:319)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote.onResume(LightfactoryRemote.java:102)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1225)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at android.app.Activity.performResume(Activity.java:3559)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2838)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2866)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2420)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at android.app.ActivityThread.access$2100(ActivityThread.java:116)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at android.os.Handler.dispatchMessage(Handler.java:99)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at android.os.Looper.loop(Looper.java:123)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at android.app.ActivityThread.main(ActivityThread.java:4203)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at java.lang.reflect.Method.invokeNative(Native Method)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at java.lang.reflect.Method.invoke(Method.java:521)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
01-02 22:04:26.672: ERROR/ActivityThread(2024): at dalvik.system.NativeStart.main(Native Method)
01-02 22:04:26.692: WARN/ActivityManager(558): Unbind failed: could not find connection for android.os.BinderProxy@43c509a8
编辑第二个
再次感谢bdls提出您的建议。我按照你的建议做了,并为服务添加了onUnBind()
覆盖。实际上只有当所有客户端都与服务断开连接时才会触发onUnBind()
,但是当我点击主页按钮时,它会被执行,然后会弹出错误消息!这对我来说没有意义,因为所有客户端都已从服务中解除绑定,那么如何破坏serviceConnection?看看:
01-03 19:38:30.837: DEBUG/LightfactoryRemote(1118): Focus onPause()1
01-03 19:38:31.577: WARN/IInputConnectionWrapper(1118): showStatusIcon on inactive InputConnection
01-03 19:38:31.587: DEBUG/LightfactoryRemote(1118): Focus onStop()
01-03 19:38:31.600: DEBUG/LightfactoryRemote(1118): Focus onDestroy() attempted to unbind service
01-03 19:38:31.607: DEBUG/LightfactoryRemote(1118): Focus onDestroy()
01-03 19:38:31.677: DEBUG/LightfactoryRemote(1125): TelnetService onUnBind()
01-03 19:38:31.727: ERROR/ActivityThread(1118): Activity com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote has leaked ServiceConnection com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote$TelnetServiceConnection@435baeb0 that was originally bound here
01-03 19:38:31.727: ERROR/ActivityThread(1118): android.app.ServiceConnectionLeaked: Activity com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote has leaked ServiceConnection com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote$TelnetServiceConnection@435baeb0 that was originally bound here
01-03 19:38:31.727: ERROR/ActivityThread(1118): at android.app.ActivityThread$PackageInfo$ServiceDispatcher.<init>(ActivityThread.java:886)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at android.app.ActivityThread$PackageInfo.getServiceDispatcher(ActivityThread.java:781)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at android.app.ApplicationContext.bindService(ApplicationContext.java:820)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at android.content.ContextWrapper.bindService(ContextWrapper.java:307)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote.onResume(LightfactoryRemote.java:102)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1225)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at android.app.Activity.performResume(Activity.java:3530)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2619)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2647)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2287)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at android.app.ActivityThread.access$1800(ActivityThread.java:112)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1692)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at android.os.Handler.dispatchMessage(Handler.java:99)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at android.os.Looper.loop(Looper.java:123)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at android.app.ActivityThread.main(ActivityThread.java:3948)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at java.lang.reflect.Method.invokeNative(Native Method)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at java.lang.reflect.Method.invoke(Method.java:521)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540)
01-03 19:38:31.727: ERROR/ActivityThread(1118): at dalvik.system.NativeStart.main(Native Method)
01-03 19:38:31.777: WARN/ActivityManager(564): Unbind failed: could not find connection for android.os.BinderProxy@4370f8a8
我认为它可能就像你说的那样,当调用unbindService()
时,对服务的绑定并不完整,但是我尝试在服务上调用一个方法,因为我支持每个活动以验证绑定完成后,它们都很顺利。
一般来说,这种行为似乎与我在每项活动中停留的时间无关。然而,一旦第一个活动泄漏了它的serviceConnection,它们就会在我之后重新执行它们。
另外一件事,如果我在开发工具中打开“立即销毁活动”,它会阻止此错误。
有什么想法吗?
答案 0 :(得分:54)
您尚未提供LightFactoryRemote
中的任何代码,因此这只是一个假设,但如果您使用bindService
方法,它看起来就像您遇到的那种问题在它自己。
要确保服务继续运行,即使已启动的活动已调用onDestroy
方法,您也应首先使用startService
。
startService州的Android文档:
使用startService()会覆盖由bindService(Intent,ServiceConnection,int)管理的默认服务生命周期:它要求服务保持运行,直到调用stopService(Intent),无论是否有任何客户端连接到它。
只要存在调用上下文,系统就会认为该服务是必需的。例如,如果此Context是一个已停止的Activity,则在恢复Activity之前,不需要该服务继续运行。
所发生的事情是绑定(并因此启动)服务的活动已停止,因此系统认为不再需要该服务并导致该错误(然后可能会停止服务)。
在此示例中,无论调用活动是否正在运行,服务都应保持运行。
ComponentName myService = startService(new Intent(this, myClass.class));
bindService(new Intent(this, myClass.class), myServiceConn, BIND_AUTO_CREATE);
第一行启动服务,第二行将其绑定到活动。
答案 1 :(得分:37)
您可以使用:
@Override
public void onDestroy() {
super.onDestroy();
if (mServiceConn != null) {
unbindService(mServiceConn);
}
}
答案 2 :(得分:30)
您绑定在onResume
但在onDestroy
中取消绑定。您应该在onPause
中进行取消绑定,以便始终匹配绑定/取消绑定对。您的间歇性错误将是您的活动暂停但未被销毁的地方,然后再次恢复。
答案 3 :(得分:13)
您只需要在onDestroy()
中取消绑定服务即可。然后,警告就会响起。
见here。
正如Activity文档试图解释的那样,有三个主要的绑定/解除绑定 您将使用的分组:onCreate()和onDestroy(),onStart()和 onStop(),onResume()和onPause()。
答案 4 :(得分:9)
你提到用户很快就在活动之间切换。可能是您在建立服务连接之前调用unbindService
?这可能会导致无法取消绑定,然后泄漏绑定。
不完全确定如何处理此问题...也许在调用onServiceConnected
时,如果已调用unbindService
,则可以调用onDestroy
。不确定这是否会奏效。
如果您还没有,可以在服务中添加onUnbind方法。这样你就可以确切地看到你的类与它解除绑定的时间,并且它可能有助于调试。
@Override
public boolean onUnbind(Intent intent) {
Log.d(this.getClass().getName(), "UNBIND");
return true;
}
答案 5 :(得分:2)
尝试在OnUserLeaveHint()中使用unbindService()。它可以防止ServiceConnection泄露的场景和其他例外情况 我在我的代码中使用它并且工作正常。
答案 6 :(得分:2)
当您绑定绑定服务时,会发生此错误。因此,sol应该是:-
在服务连接中添加serviceBound,如下所示:
20/07/20 15:28:14 INFO mapred.SparkHadoopMapRedUtil: attempt_20200720152813_0001_m_000000_0: Committed
20/07/20 15:28:14 INFO executor.Executor: Finished task 0.0 in stage 1.0 (TID 1). 1224 bytes result sent to driver
20/07/20 15:28:14 INFO scheduler.TaskSetManager: Finished task 0.0 in stage 1.0 (TID 1) in 83 ms on localhost (executor driver) (1/1)
20/07/20 15:28:14 INFO scheduler.TaskSchedulerImpl: Removed TaskSet 1.0, whose tasks have all completed, from pool
20/07/20 15:28:14 INFO scheduler.DAGScheduler: ResultStage 1 (run at AccessController.java:0) finished in 0.085 s
20/07/20 15:28:14 INFO scheduler.DAGScheduler: Job 1 finished: run at AccessController.java:0, took 0.119817 s
20/07/20 15:28:14 INFO metastore.HiveMetaStore: 6: get_table : db=ben_test2 tbl=t22
20/07/20 15:28:14 INFO HiveMetaStore.audit: ugi=benhdfs ip=unknown-ip-addr cmd=get_table : db=ben_test2 tbl=t22
20/07/20 15:28:14 INFO metastore.HiveMetaStore: 6: get_table : db=ben_test2 tbl=t22
20/07/20 15:28:14 INFO HiveMetaStore.audit: ugi=benhdfs ip=unknown-ip-addr cmd=get_table : db=ben_test2 tbl=t22
20/07/20 15:28:14 ERROR thriftserver.SparkExecuteStatementOperation: Error executing query, currentState RUNNING,
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.spark.sql.hive.client.Shim_v0_14.loadTable(HiveShim.scala:716)
at org.apache.spark.sql.hive.client.HiveClientImpl$$anonfun$loadTable$1.apply$mcV$sp(HiveClientImpl.scala:672)
at org.apache.spark.sql.hive.client.HiveClientImpl$$anonfun$loadTable$1.apply(HiveClientImpl.scala:672)
at org.apache.spark.sql.hive.client.HiveClientImpl$$anonfun$loadTable$1.apply(HiveClientImpl.scala:672)
at org.apache.spark.sql.hive.client.HiveClientImpl$$anonfun$withHiveState$1.apply(HiveClientImpl.scala:283)
at org.apache.spark.sql.hive.client.HiveClientImpl.liftedTree1$1(HiveClientImpl.scala:230)
at org.apache.spark.sql.hive.client.HiveClientImpl.retryLocked(HiveClientImpl.scala:229)
at org.apache.spark.sql.hive.client.HiveClientImpl.withHiveState(HiveClientImpl.scala:272)
at org.apache.spark.sql.hive.client.HiveClientImpl.loadTable(HiveClientImpl.scala:671)
at org.apache.spark.sql.hive.HiveExternalCatalog$$anonfun$loadTable$1.apply$mcV$sp(HiveExternalCatalog.scala:741)
at org.apache.spark.sql.hive.HiveExternalCatalog$$anonfun$loadTable$1.apply(HiveExternalCatalog.scala:739)
at org.apache.spark.sql.hive.HiveExternalCatalog$$anonfun$loadTable$1.apply(HiveExternalCatalog.scala:739)
at org.apache.spark.sql.hive.HiveExternalCatalog.withClient(HiveExternalCatalog.scala:95)
at org.apache.spark.sql.hive.HiveExternalCatalog.loadTable(HiveExternalCatalog.scala:739)
at org.apache.spark.sql.hive.execution.InsertIntoHiveTable.sideEffectResult$lzycompute(InsertIntoHiveTable.scala:323)
at org.apache.spark.sql.hive.execution.InsertIntoHiveTable.sideEffectResult(InsertIntoHiveTable.scala:170)
at org.apache.spark.sql.hive.execution.InsertIntoHiveTable.doExecute(InsertIntoHiveTable.scala:347)
at org.apache.spark.sql.execution.SparkPlan$$anonfun$execute$1.apply(SparkPlan.scala:114)
at org.apache.spark.sql.execution.SparkPlan$$anonfun$execute$1.apply(SparkPlan.scala:114)
at org.apache.spark.sql.execution.SparkPlan$$anonfun$executeQuery$1.apply(SparkPlan.scala:135)
at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151)
at org.apache.spark.sql.execution.SparkPlan.executeQuery(SparkPlan.scala:132)
at org.apache.spark.sql.execution.SparkPlan.execute(SparkPlan.scala:113)
at org.apache.spark.sql.execution.QueryExecution.toRdd$lzycompute(QueryExecution.scala:87)
at org.apache.spark.sql.execution.QueryExecution.toRdd(QueryExecution.scala:87)
at org.apache.spark.sql.Dataset.<init>(Dataset.scala:185)
at org.apache.spark.sql.Dataset$.ofRows(Dataset.scala:64)
at org.apache.spark.sql.SparkSession.sql(SparkSession.scala:592)
at org.apache.spark.sql.SQLContext.sql(SQLContext.scala:699)
at org.apache.spark.sql.hive.thriftserver.SparkExecuteStatementOperation.org$apache$spark$sql$hive$thriftserver$SparkExecuteStatementOperation$$execute(SparkExecuteStatementOperation.scala:220)
at org.apache.spark.sql.hive.thriftserver.SparkExecuteStatementOperation$$anon$1$$anon$2.run(SparkExecuteStatementOperation.scala:163)
at org.apache.spark.sql.hive.thriftserver.SparkExecuteStatementOperation$$anon$1$$anon$2.run(SparkExecuteStatementOperation.scala:160)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:422)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1762)
at org.apache.spark.sql.hive.thriftserver.SparkExecuteStatementOperation$$anon$1.run(SparkExecuteStatementOperation.scala:173)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalArgumentException: Wrong FS: hdfs://ns1:8020/user/hive/warehouse/ben_test2.db/t22/.hive-staging_hive_2020-07-20_15-28-13_926_2879151902947429298-2/-ext-10000/part-00000, expected: hdfs://ns1
at org.apache.hadoop.fs.FileSystem.checkPath(FileSystem.java:647)
at org.apache.hadoop.hdfs.DistributedFileSystem.getPathName(DistributedFileSystem.java:194)
at org.apache.hadoop.hdfs.DistributedFileSystem.getEZForPath(DistributedFileSystem.java:2093)
at org.apache.hadoop.hdfs.client.HdfsAdmin.getEncryptionZoneForPath(HdfsAdmin.java:289)
at org.apache.hadoop.hive.shims.Hadoop23Shims$HdfsEncryptionShim.isPathEncrypted(Hadoop23Shims.java:1221)
at org.apache.hadoop.hive.ql.metadata.Hive.moveFile(Hive.java:2607)
at org.apache.hadoop.hive.ql.metadata.Hive.copyFiles(Hive.java:2711)
at org.apache.hadoop.hive.ql.metadata.Hive.loadTable(Hive.java:1645)
... 45 more
20/07/20 15:28:14 ERROR thriftserver.SparkExecuteStatementOperation: Error running hive query:
org.apache.hive.service.cli.HiveSQLException: java.lang.reflect.InvocationTargetException
at org.apache.spark.sql.hive.thriftserver.SparkExecuteStatementOperation.org$apache$spark$sql$hive$thriftserver$SparkExecuteStatementOperation$$execute(SparkExecuteStatementOperation.scala:258)
at org.apache.spark.sql.hive.thriftserver.SparkExecuteStatementOperation$$anon$1$$anon$2.run(SparkExecuteStatementOperation.scala:163)
at org.apache.spark.sql.hive.thriftserver.SparkExecuteStatementOperation$$anon$1$$anon$2.run(SparkExecuteStatementOperation.scala:160)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:422)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1762)
at org.apache.spark.sql.hive.thriftserver.SparkExecuteStatementOperation$$anon$1.run(SparkExecuteStatementOperation.scala:173)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
};
取消对onDestroy的服务
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;
}
答案 7 :(得分:1)
您可以使用布尔值来控制它,因此只有在绑定时才调用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;
}
};
答案 8 :(得分:0)
活动中绑定的每个服务都必须在应用关闭时取消绑定。
所以尝试使用
onPause(){
unbindService(YOUR_SERVICE);
super.onPause();
}
答案 9 :(得分:0)
我最近一直在阅读有关Android Service的文章,并有机会深入了解它。我遇到了服务泄漏,就我的情况而言,这是因为我有一个未绑定服务正在启动已绑定服务,但在此情况下,我的未绑定服务由活动代替。
因此,当我使用 stopSelf()停止我的未绑定服务时,发生了泄漏,原因是我在不取消绑定服务的情况下停止了父服务。现在,绑定服务正在运行,并且不知道它属于谁。
简单直接的解决方法是,您应该在父活动/服务的 onDestroy()函数中调用 unbindService(YOUR_SERVICE); 。这样,生命周期将确保在父活动/服务出现故障之前停止或清理绑定的服务。
此问题还有另一种形式。有时,在绑定服务中,您希望某些功能仅在绑定服务时才起作用,因此我们最终在onServiceConnected中放入绑定标志,例如:
public void onServiceConnected(ComponentName name, IBinder service) {
bounded = true;
// code here
}
直到现在都可以正常工作,但是当我们将onServiceDisconnected函数作为 unbindService 函数调用的回调时,问题就来了,仅当服务被终止时,才通过文档调用此函数或崩溃。您将从不从相同线程中获得此回调。因此,我们最终会做类似的事情:
public void onServiceDisconnected(ComponentName name) {
bounded = false;
}
这会在代码中造成重大错误,因为我们的 bound标志永远不会重置为false,并且在大多数情况下,当此服务再次连接回true
时。因此,为避免出现这种情况,应在呼叫bound
时将unbindService
设置为false。
这是Erik的blog中更详细的介绍。
希望来到这里的人感到好奇。