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

问题描述 投票:-1回答:1

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

当发生某些事情时,我正试图实现从服务中显示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

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

android kotlin android-service android-context
1个回答
3
投票

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

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

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

不,你需要Activity对象,正如你的演员看到的那样。

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

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

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

  • 您有一个可见的活动,然后该活动可以通过某种适当的方式让用户知道该事件(例如,小吃店)
  • 您没有可见的活动,在这种情况下,服务可能会发出通知,或者可能只是丢弃事件(如果用户不在应用程序的UI中,则无需让用户知道它)

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

  • 该服务在公交车上发布活动
  • 每个活动在可见的情况下订阅公交车的事件,在不再可见时取消订阅(例如,通过onStart() / onStop()
  • 如果活动获得事件,它会向用户显示快餐栏(或其他)
  • 如果服务确定没有任何事件发生,它会使用一些后备方法

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

This sample app用greenrobot的EventBus演示了这种方法,而this sample appLocalBroadcastManager演示了这种方法。

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

© www.soinside.com 2019 - 2024. All rights reserved.