Android Worker 中的 Firebase 事件监听器
Firebase Event Listener inside Android Worker
我正在尝试从 Android WorkManager 实现一个 Worker,并带有一个事件侦听器以供 Firebase 数据库参考。如果应用程序在 foreground/background 中,它可以正常工作。但是一旦我关闭应用程序并且工作人员运行事件侦听器就不会触发,据我所知我没有在日志中收到与此相关的任何错误消息。
这是一个示例代码:
class FirebaseWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
override fun doWork(): Result {
val firebaseDatabaseRef = FirebaseDatabase.getInstance().reference
firebaseDatabaseRef.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
// Handle DataSnapshot
}
override fun onCancelled(databaseError: DatabaseError) {
// Handle DatabaseError
}
})
return Result.SUCCESS
}
}
如果我可以做些什么来在应用程序关闭时在后台获取和处理 Firebase 实时数据库数据,请告诉我。
如我所见,您使用的是addListenerForSingleValueEvent()
,这意味着侦听器将精确读取一次数据。这意味着您的 onDataChange()
方法会被当前值触发(如果可用,则从缓存中触发,否则从 Firebase 服务器中触发),然后立即停止监听。在这种情况下,无需删除侦听器。唯一需要取消 addListenerForSingleValueEvent
的情况是当您附加它时没有网络连接并且客户端没有数据的本地副本,要么是因为有另一个活动的侦听器,要么是因为它有一个副本磁盘上的数据。
如果你想一直监听变化,你应该使用addValueEventListener()
。使用这种侦听器意味着您的 onDataChange()
方法会立即使用当前数据调用,但是(与 addListenerForSingleValueEvent
不同)侦听器将在此之后保持活动状态,稍后将调用您的 onDataChange()
也有变化。
您可以在 Android 应用程序关闭后使用 addValueEventListener()
,而不是将其删除。通常,一旦你使用了监听器,你还需要根据activity的生命周期 。如果不删除侦听器,该应用程序将只能运行一段时间,因为如果该应用程序不在前台,Android 将停止您的服务。它这样做是为了在应用程序未被使用时节省资源。它还可能会阻止您的应用程序进行任何联网,甚至完全终止应用程序进程。正如您已经提到的,除了将其设为前台服务外,您无法采取任何措施来防止这种情况发生。
前台服务可能不是适合您的情况的最佳选择,也不是适合您的用户的最佳选择。详细了解 limitations on background services。
我的建议是使用 Firebase Cloud Messaging 在它可能感兴趣的某些更改时通知您的应用程序。这样即使您的用户将关闭他们的应用程序,他们也会收到通知。
您需要阻止 doWork()
的执行,直到所有工作完成。现在,由于 addListenerForSingleValueEvent
是异步的,您的函数会立即 returning SUCCESS
,这意味着 WorkManager 假定一切都已完成并允许您的应用进程停止。
阻止函数的一种方法是使用 CountDownLatch 强制代码等待侦听器完成:
override fun doWork(): Result {
val latch = CountDownLatch(1)
val firebaseDatabaseRef = FirebaseDatabase.getInstance().reference
firebaseDatabaseRef.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
// Handle DataSnapshot
latch.countDown()
}
override fun onCancelled(databaseError: DatabaseError) {
// Handle DatabaseError
latch.countDown()
}
})
latch.await()
return Result.SUCCESS
}
您可能还想考虑何时 return 不同的结果代码,以便告诉 WorkManager 您完成的工作是否应该重试。
我正在尝试从 Android WorkManager 实现一个 Worker,并带有一个事件侦听器以供 Firebase 数据库参考。如果应用程序在 foreground/background 中,它可以正常工作。但是一旦我关闭应用程序并且工作人员运行事件侦听器就不会触发,据我所知我没有在日志中收到与此相关的任何错误消息。
这是一个示例代码:
class FirebaseWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
override fun doWork(): Result {
val firebaseDatabaseRef = FirebaseDatabase.getInstance().reference
firebaseDatabaseRef.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
// Handle DataSnapshot
}
override fun onCancelled(databaseError: DatabaseError) {
// Handle DatabaseError
}
})
return Result.SUCCESS
}
}
如果我可以做些什么来在应用程序关闭时在后台获取和处理 Firebase 实时数据库数据,请告诉我。
如我所见,您使用的是addListenerForSingleValueEvent()
,这意味着侦听器将精确读取一次数据。这意味着您的 onDataChange()
方法会被当前值触发(如果可用,则从缓存中触发,否则从 Firebase 服务器中触发),然后立即停止监听。在这种情况下,无需删除侦听器。唯一需要取消 addListenerForSingleValueEvent
的情况是当您附加它时没有网络连接并且客户端没有数据的本地副本,要么是因为有另一个活动的侦听器,要么是因为它有一个副本磁盘上的数据。
如果你想一直监听变化,你应该使用addValueEventListener()
。使用这种侦听器意味着您的 onDataChange()
方法会立即使用当前数据调用,但是(与 addListenerForSingleValueEvent
不同)侦听器将在此之后保持活动状态,稍后将调用您的 onDataChange()
也有变化。
您可以在 Android 应用程序关闭后使用 addValueEventListener()
,而不是将其删除。通常,一旦你使用了监听器,你还需要根据activity的生命周期
前台服务可能不是适合您的情况的最佳选择,也不是适合您的用户的最佳选择。详细了解 limitations on background services。
我的建议是使用 Firebase Cloud Messaging 在它可能感兴趣的某些更改时通知您的应用程序。这样即使您的用户将关闭他们的应用程序,他们也会收到通知。
您需要阻止 doWork()
的执行,直到所有工作完成。现在,由于 addListenerForSingleValueEvent
是异步的,您的函数会立即 returning SUCCESS
,这意味着 WorkManager 假定一切都已完成并允许您的应用进程停止。
阻止函数的一种方法是使用 CountDownLatch 强制代码等待侦听器完成:
override fun doWork(): Result {
val latch = CountDownLatch(1)
val firebaseDatabaseRef = FirebaseDatabase.getInstance().reference
firebaseDatabaseRef.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
// Handle DataSnapshot
latch.countDown()
}
override fun onCancelled(databaseError: DatabaseError) {
// Handle DatabaseError
latch.countDown()
}
})
latch.await()
return Result.SUCCESS
}
您可能还想考虑何时 return 不同的结果代码,以便告诉 WorkManager 您完成的工作是否应该重试。