【问题标题】:How to get live data from WorkManager in Android如何从 Android 中的 WorkManager 获取实时数据
【发布时间】:2020-01-22 12:46:53
【问题描述】:


我正在尝试从 WorkManagerdoWork() 方法进行 API 调用。我收到MutableLiveData 和回复列表。如何将此复杂对象设置为 WorkManager 的输出。
请在下面找到相同的实现:

class FetchWorkManager(context: Context, params: WorkerParameters): Worker(context,params) {
var postInfoLiveData: LiveData<List<PostInfo>> = MutableLiveData()

@SuppressLint("RestrictedApi")
override fun doWork(): Result {
    fetchInfoFromRepository()
    //setting output data
    val data = Data.Builder()
        .putAll(postInfoLiveData)
        //.put("liveData",postInfoLiveData)
        .build()
    return Result.success(data)
}


fun fetchInfoFromRepository(){
    val retrofitRepository = RetrofitRepository()
    postInfoLiveData = retrofitRepository.fetchPostInfoList()

}

}


谁能帮我解决这个问题。

【问题讨论】:

  • 您可以将响应列表数据存储在Room Database 中,即使您的应用程序正在后台运行
  • 但是如何在 doWork() 方法中设置从 Web 服务接收的 LiveData。对于原始对象,这很好。有没有办法将自定义对象(如 LiveData)设置为输出数据

标签: android android-jetpack android-mvvm


【解决方案1】:

我不确定,但应该是这样的:)

workManager?.getWorkInfoByIdLiveData(oneTimeWorkRequest.id)
                ?.observe(this, Observer {
                    if (it?.state == null)
                        return@Observer
                    when (it.state) {
                        State.SUCCEEDED -> {
                            val successOutputData = it.outputData

                        }
                        State.FAILED -> {
                            val failureOutputData = it.outputData

                        }
                    }
                })

【讨论】:

  • 但是如何在 doWork() 方法中设置从 Web 服务接收的 LiveData。对于原始对象,这很好。有没有办法将自定义对象(如 LiveData)设置为输出数据
【解决方案2】:

WorkerLiveData 成员返回结果不是预期行为。 Worker 的结果应该作为startWork 方法的返回值返回。用一些数据构造Result 对象ListenableWorker.Result.success 方法可以使用。

const val WORKER_RESULT_INT = "WORKER_RESULT_INT"

class WorkerWithOutput(context: Context, params: WorkerParameters) : Worker(context, params) {
    override fun doWork(): Result {
        // do some work
        return Result.success(Data.Builder().putInt(WORKER_RESULT_INT, 123).build())
    }
}

并且要从getWorkInfoXXX 方法之一之外获取此数据。

fun getResult(context: Context, owner: LifecycleOwner, id: UUID) {
    WorkManager.getInstance(context)
            .getWorkInfoByIdLiveData(id)
            .observe(owner, Observer {
                if (it.state == WorkInfo.State.SUCCEEDED) {
                    val result = it.outputData.getInt(WORKER_RESULT_INT, 0)
                    // do something with result
                }
            })
}

活动或片段可以作为LifecycleOwner 传递(取决于您的情况)。 WorkRequest.getId 用于获取id 的作品。

值得注意的是,ListenableWorker.setProgressAsync 在这种情况下也很有用。

【讨论】:

  • 但是如何在 doWork() 方法中设置从 Web 服务接收的 LiveData。对于原始对象,这很好。有没有办法将 LiveData 等自定义对象设置为输出数据
  • @Android_programmer_office 不幸的是,不能将LiveData oject 放入Data。甚至不可能将Parcleable 放入Data(与Bundle 不同)。 Data 类被设计成可以持久化到数据库中——这个要求限制了可以放入Data 对象的数据类型集。
  • WorkManager 不适用于查询数据,它适用于独立于 UI 工作流的后台任务。这个link 可能有助于更好地理解其目的。后台查询数据最好使用RxJava或kotlin协程。
【解决方案3】:

我不确定这是否可行,因为我还没有尝试过。我知道这是一个迟到的答案,但我鼓励你尝试使用 CoroutineWorker,如下所示:

class MyWorker(context: Context, params: WorkerParameters):
    CoroutineWorker(context, params){
    override suspend fun doWork(): Result {

      val data = withContext(Dispatchers.IO) {
         // you can make network request here (best practice?)
         return@withContext fetchInfoFromRepository()
         // make sure that fetchInfoFromRepository() returns  LiveData<List<PostInfo>>
      }
    
      /* Then return it as result with a KEY (DATA_KEY) to use in UI. */
      val result = workDataOf(DATA_KEY to data)
      return Result.success(result)
   }
}

参考:https://developer.android.com/topic/libraries/architecture/workmanager/advanced/coroutineworker

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    • 2020-05-27
    相关资源
    最近更新 更多