如何在服务中获取上下文(不是applicationContext)

时间:2018-05-01 23:10:07

标签: android kotlin android-service android-context

是否可以引用服务中的上下文,但不能使用应用程序上下文?

我正在努力实现在发生某些事情时从服务中显示snackbar的能力。这应该在MULTIPLE活动中完成。 为此,我需要上下文,然后从中引用以使用此行获取视图:

View rootView = ((Activity)context).getWindow().getDecorView().findViewById(android.R.id.content)

我在服务中这样做:

class MyService : Service() {

override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
//TODO do something useful

val view: View = (this.applicationContext as Activity).window.decorView.findViewById(android.R.id.content)
Timber.d("some jobe done")
return Service.START_NOT_STICKY
  }

override fun onBind(intent: Intent): IBinder? {
//TODO for communication return IBinder implementation
   return null
 }
}

但是,在引用应用程序上下文时,我会收到错误,并将其强制转换为Activty:

Caused by: java.lang.ClassCastException: com.myapp.Application cannot be cast to android.app.Activity

是否可以正确处理(参考我的用例)?

1 个答案:

答案 0 :(得分:3)

  

我正在努力实现在发生某些事情时从服务中显示小吃吧的能力。

这不是一个好主意。例如,它没有解决您没有正在运行的活动的情况。

  

要做到这一点,我需要上下文,然后从中引用以使用此行获取视图:

不,你需要Activity对象,正如你的演员所见。

  

是否可以正确处理(参考我的用例)?

不是你正在接近问题的方式。

您的情况是:服务检测到某个事件,并且该服务希望让用户知道该事件。有两种可能性:

  • 您有一个可见的活动,然后该活动可以通过某种适当的方式让用户了解该事件(例如,小吃店)

  • 您没有可见的活动,在这种情况下,服务可能会发出通知,或者可能只是放弃事件(如果用户不是,则无需让用户知道它)在应用程序的UI中)

解决此问题的典型方法是使用某种形式的事件总线(LocalBroadcastManager,greenrobot的EventBus或任意数量的基于RxJava的事件总线实现):

  • 服务在公交车上发布活动

  • 每个活动都会在可见的情况下订阅公交车的事件,在不再可见时取消订阅(例如,通过onStart() / onStop()

  • 如果活动获得该活动,它会向用户显示小吃栏(或其他)

  • 如果服务确定没有收到任何事件,则会使用一些后备方法

这种方法可以更好地分离关注点,因为服务不应该关心UI如何让用户了解事件。它还可以干净地处理您没有可用于小吃店的活动的情况。

This sample app用greenrobot的EventBus演示了这种方法 this sample app使用LocalBroadcastManager演示了这种方法。

还有其他解决方案不涉及真正的事件总线,例如更新存储库的服务,它通过反应方式更新UI组件(例如,RxJava导致LiveData)。但是,服务不应该试图直接操纵活动的UI,部分原因可能是没有活动。