协程值得与类型映射一起使用吗?

Are coroutines worth using with type mapping?

是否值得调用协程来执行类型映射操作?或者它会导致过多的代码膨胀 and/or 开销?

所以场景如下:


Transformations.map 代码看起来像这样

fun doSomethingWithRepoData(repoData: LiveData<List<A>>): LiveData<List<GUI_A>> =
    Transformations.map(repoData) { 
        it.map { GUI_A.fromRepoObject(it) }
    }

函数 fromRepoObject 仅将第一个对象的属性映射到第二个对象的新实例。


想法是在map函数中使用协程来提高性能;但我不知道这是否值得麻烦:

fun doSomethingWithRepoData(repoData: LiveData<List<A>>): LiveData<List<GUI_A>> =
    Transformations.map(repoData) { 
        it.map { async { GUI_A.fromRepoObject(it) } }
          .map { it.await() }
    }

我讨厌的最终答案是这取决于

切换线程的上下文不是免费的,这样做会产生一些累积的开销,因此在考虑一件事或另一件事之前,您必须注意数据的大小。

  • 映射 15 个元素?可能不值得。
  • 映射1000?可能是!他们是否有嵌套的列表和地图也应该被映射?
  • 映射1_000_000?绝对!

我们还应该注意我们的映射实现。

给出的例子:

fun doSomethingWithRepoData(repoData: LiveData<List<A>>): LiveData<List<GUI_A>> =
    Transformations.map(repoData) { 
        it.map { async { GUI_A.fromRepoObject(it) } }
          .map { it.await() }
    }

不要这样做。

你看; LiveData 确保观察 LiveData 的代码在主线程上是 运行。一方面这很好,因为它确保了主线程的安全,但另一方面它在这种情况下是 "bad",因为主线程在推送值之前等待所有协程完成它们的映射操作。

一个更聪明的方法,假设我们在 ViewModel 可能是:

class SampleVM: ViewModel(){

    fun doSomethingWithRepoData(repoData: LiveData<List<A>>): LiveData<List<GUI_A>> = 
    Transformations.switchMap(repoData) { listA ->
        val result = MutableLiveData<List<GUI_A>>()
        // Don't block the UI thread by running in a coroutine
        viewModelScope.launch {
            listA
                 // Parallelize computation
                 .map { async(Dispatchers.Default) { GUI_A.fromRepoObject(it) }
                 // The viewModelScope job will await for all coroutines to finish mapping
                 .map { it.await() }
                 // Post the result to into the live data
                 .let { result.postValue(it) }
        }

        result
    }


}