是否可以引用服务中的上下文,但不能使用应用程序上下文?
我正在努力实现在发生某些事情时从服务中显示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
是否可以正确处理(参考我的用例)?
答案 0 :(得分:3)
我正在努力实现在发生某些事情时从服务中显示小吃吧的能力。
这不是一个好主意。例如,它没有解决您没有正在运行的活动的情况。
要做到这一点,我需要上下文,然后从中引用以使用此行获取视图:
不,你需要Activity
对象,正如你的演员所见。
是否可以正确处理(参考我的用例)?
不是你正在接近问题的方式。
您的情况是:服务检测到某个事件,并且该服务希望让用户知道该事件。有两种可能性:
您有一个可见的活动,然后该活动可以通过某种适当的方式让用户了解该事件(例如,小吃店)
您没有可见的活动,在这种情况下,服务可能会发出通知,或者可能只是放弃事件(如果用户不是,则无需让用户知道它)在应用程序的UI中)
解决此问题的典型方法是使用某种形式的事件总线(LocalBroadcastManager
,greenrobot的EventBus或任意数量的基于RxJava的事件总线实现):
服务在公交车上发布活动
每个活动都会在可见的情况下订阅公交车的事件,在不再可见时取消订阅(例如,通过onStart()
/ onStop()
)
如果活动获得该活动,它会向用户显示小吃栏(或其他)
如果服务确定没有收到任何事件,则会使用一些后备方法
这种方法可以更好地分离关注点,因为服务不应该关心UI如何让用户了解事件。它还可以干净地处理您没有可用于小吃店的活动的情况。
This sample app用greenrobot的EventBus演示了这种方法
this sample app使用LocalBroadcastManager
演示了这种方法。
还有其他解决方案不涉及真正的事件总线,例如更新存储库的服务,它通过反应方式更新UI组件(例如,RxJava导致LiveData
)。但是,服务不应该试图直接操纵活动的UI,部分原因可能是没有活动。