【问题标题】:How to use workmanager as an upload service如何使用 workmanager 作为上传服务
【发布时间】:2021-10-18 14:37:44
【问题描述】:

我正在构建一个离线第一个聊天应用程序,因此我使用Workmanager 来处理POST 发送聊天消息的请求。

我正在学习 android 开发,所以我需要一些关于构建聊天消息上传的帮助

当前实现

当需要发布新的聊天消息时,客户端会执行以下操作

  1. 使用带有新 UUID 的 Room 将聊天保存到 SQLite
  2. 启动工作经理unique work 来发布此消息
  3. 这样我可以确保当客户端有互联网时消息最终会发布

这是理想的吗?我发现了一些问题。

  1. 我开始的工人太多了。每条消息都有一个工作请求。
  2. 发布到服务器的消息的年表丢失。

更好的实现

  1. POST 消息的单个唯一工作人员。这将获取所有离线消息并以正确的顺序发布它们

还是不理想

这些实现的问题是:

  1. 一旦开始,您对工作的控制权就很小(不是那么容易)。
    • 如果工作失败,我们设置了退避时间。因此,当要发送新消息时,我们需要用新的工作请求替换旧的工作人员。这似乎并不理想。

    我们正在改变工作人员,而不是向队列追加新任务。

    • 我们不能在每个消息实现中使用一个工人,因为我们松散了年表并且工人太多

这是一个分布式系统问题。

  • 我们正在启动工作人员,他们应该独立于应用程序的生命周期工作
  • 工人应该在他们死亡的情况下活着回来(已经由android-workmanager管理)
  • 工作人员应该从要执行的任务队列中读取(这是我正在寻找的)
  • 应该有一个持久性存储充当工作人员的队列
  • 应该有一个服务或工厂在需要时调用工人(我们在当前的 impl 中没有这个)

问题

  1. 当客户端有互联网时,是否有更好的方法将离线消息发布到服务器?喜欢服务?
  2. 是否有这样做的社区构建库?
  3. 当前的实现可以扩展到文件吗?

【问题讨论】:

  • 您可以使用 workmanager,但您需要房间数据库中的密钥 isSent - false。如果网络通过工作管理器或服务(根据您的意愿进行交流)连接命中后请求,但当您获得成功时,请更新 isSent - true,因此在建立连接时无法再次发送
  • @DeePanShu 是的,我已经在这样做了。而且我也已经实现了“一个工人来做所有的帖子”。但我的问题是是否有更好的方法。我将更改为什么我认为当前的实现不令人满意的问题。
  • @clmno 您使用的是哪种语言?这是必需的,因此我可以用该语言发布答案。
  • @VaibhavGoyal 我正在使用 Kotlin,但我不认为这取决于语言。这是一个 android 子系统问题。
  • @clmno a/c 据我所知,我认为没有令人满意的实现,因为当我们在应用中实现聊天时,最好的优化总是实时框架。

标签: android android-workmanager


【解决方案1】:

是的,您可以使用服务来有效地同步消息,首先创建一个从实时数据类扩展的对象,以获取网络更新的实时更新,

object NetworkState : LiveData<Boolean>() {

private lateinit var application: Application
private lateinit var networkRequest: NetworkRequest
private lateinit var connectivityManager: ConnectivityManager

fun init(application: Application) {
    this.application = application
    connectivityManager = application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    networkRequest = NetworkRequest.Builder()
        .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .build()
}

override fun onActive() {
    super.onActive()
    getDetails()
}

private fun getDetails() {

    connectivityManager.registerNetworkCallback(networkRequest, object : ConnectivityManager.NetworkCallback() {

        override fun onAvailable(network: Network) {
            super.onAvailable(network)
            postValue(true)
        }

        override fun onLost(network: Network) {
            super.onLost(network)
            postValue(false)
        }

        override fun onUnavailable() {
            super.onUnavailable()
            postValue(false)
        }
    })
}

然后像这样在你的 Application 类中初始化它,

@HiltAndroidApp
class BaseApplication : Application(), Configuration.Provider {

@Inject
lateinit var workerFactory: HiltWorkerFactory

override fun getWorkManagerConfiguration() =
    Configuration.Builder()
        .setWorkerFactory(workerFactory)
        .build()

override fun onCreate() {
    super.onCreate()
    NetworkState.init(this)
    if (BuildConfig.DEBUG){
        Timber.plant(Timber.DebugTree())
    }
}
}

现在您可以创建一个从生命周期服务扩展而来的服务类,并观察那里更新的网络。当 Live Data 发出值 true 时,您可以检查是否有需要在线同步的消息。但请记住,它仅在应用程序处于前台时才有效。

【讨论】:

  • 看起来不错。但这适用于应用程序“活着”的情况。我正在使用观察网络状态并同步消息的 websocket 服务。但我的问题是针对未打开应用程序时的工作经理和离​​线消息同步。
  • 这其实很好。我应该为我的 websocket 服务实现这一点。但同样,当应用程序关闭但仍有消息或文件要发送时怎么办。将 WhatsApp 视为离线同步。
  • 为此使用定期工作管理器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多