【问题标题】:When can you call a bound service in the Android Activity lifecycle?Android Activity 生命周期中什么时候可以调用绑定的服务?
【发布时间】:2012-09-07 11:18:25
【问题描述】:

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

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

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

mConnection 是一个 ServiceConnection 对象,我已经在匿名类中重写了 onServiceConnected 回调方法

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

mService = binder.getService();

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

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

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 回调的正文中访问它吗?

【问题讨论】:

    标签: android android-activity android-service


    【解决方案1】:

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

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

    在 onServiceConnected 中:

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

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

    【讨论】:

    【解决方案2】:

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

    上面写着:

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

    【讨论】:

      【解决方案3】:

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

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-04
        • 1970-01-01
        • 1970-01-01
        • 2023-03-14
        • 1970-01-01
        • 1970-01-01
        • 2013-04-06
        • 2013-07-10
        相关资源
        最近更新 更多