3

我对 Android 开发人员很陌生,并且在绑定服务的概念上苦苦挣扎

我已在活动的onCreate方法中将服务绑定到活动

startService(intent);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

mConnection是我在匿名类中ServiceConnection重写了回调方法的对象onServiceConnected

在回调中,mService(它是 type 的类成员LibraryServiceLibraryService是我的子类Service)设置为引用LibraryService我们绑定到的对象:

mService = binder.getService();

我以为在 onCreate 中调用 bindService 之后,我就可以通过 mService 引用调用 LibraryService 了,但此时它仍然设置为 null,表示尚未执行 onServiceConnected 回调。

我试图打印由mService使用 Log 的方法生成的字符串的值:

if (mService != null) {
    Log.d(LOG_TAG, "In onCreate getLogFileName string value: " + mService.getLogFileName("pulse"));             
} else {
    Log.d(LOG_TAG, "In onCreate getLogFileName string value: null");                
}

正如我提到的 - 它在 onCreate 中仍然为空,然后我将相同的日志代码添加到 onStart 和 onResume 但 mService 仍然为空

我的问题是该回调何时执行?我原以为它必须发生在onCreate方法的主体内,但显然不是。我想我需要一些关于 Android 系统如何/何时执行回调的指示

我知道回调确实会被执行,因为我在实例化 mService 的语句上放置了一个断点并且它命中了该语句。我只是不明白它什么时候发生,即我怎么知道它什么时候可以假设mService已经设置?我只能在OnServiceConnected回调正文中访问它吗?

4

3 回答 3

2

服务绑定是异步的,因此,您必须通过一点同步来处理它。因此,在调用绑定服务后,您可以执行类似的操作

synchronized(this){
   while(mBoundInstance == null)
      this.wait();
}

在 onServiceConnected 中:

synchronized(this){
   this.notify(); //wakes up thread: now mBoundInstance is 100% != null
}

请注意,将等待放在 asyncTask 中很好,这样 ui 就不会被冻结。

于 2012-09-07T11:24:05.217 回答
0

看看https://stuff.mit.edu/afs/sipb/project/android/docs/guide/components/bound-services.html

那里说:

  • 您只需要在活动可见时与服务交互,您应该在 onStart() 期间绑定并在 onStop() 期间取消绑定。
  • 如果您希望您的活动即使在后台停止时也能收到响应,那么您可以在 onCreate() 期间绑定并在 onDestroy() 期间取消绑定。请注意,这意味着您的活动需要在其运行的整个过程中(即使在后台)都使用该服务,因此如果该服务在另一个进程中,那么您会增加该进程的权重,并且系统更有可能会杀了它。
  • 您通常不应在活动的 onResume() 和 onPause() 期间绑定和取消绑定
于 2020-05-06T14:57:00.403 回答
0

现在我重新阅读了您的问题和描述,我认为您想了解其他信息。我不会删除第一个答案,因为如果只阅读问题的标题,它通常是正确的答案。

通常你想在 onResume 中/之后真正构建你的 UI。或者您将启动一个定期轮询您的服务的线程 - 并在 onResume 上启动该线程(并在 onPause 上停止它)。您可以将该“init”代码移至特殊的 init() 方法。

onStart 你调用 bindService onResume 你检查 mService 是否不为空,然后你启动 init() 方法(如果你只是将你的活动放在后台,它不为空,那么它不会超过 onStop,而只会调用 onPause 和 onResume)。

您还可以在从活页夹对象分配 mService 之后立即从 ServiceConnection 匿名类调用 init() 。

请记住,在 ServiceConnectionon.ServiceDisconnected 中以及在 onStop() 中调用 unbindService() 之后,始终将 mService 设为空。还要记住:在完成一次绑定(和取消绑定)后,您不能重新使用 ServiceConnection 对象。它会给出一个例外。因此,只需在每个新绑定(onStart/onStop 的每个周期)上执行一个新的 ServiceConnection。

于 2020-05-06T15:27:30.410 回答