在 Dispatchers.IO 线程上使用 liveData{} 协程构建器
Using liveData{} coroutine builder on Dispatchers.IO thread
我的代码
fun weatherByCity(cityName: String): LiveData<Resource<Response>> = liveData(Dispatchers.IO) {
val response = appRepository.weatherByCity(cityName)
emit(response)
}
fun weatherByZipCode(zipCode: String): LiveData<Resource<Response>> = liveData(Dispatchers.IO) {
val response = appRepository.weatherByZipCode(zipCode)
emit(response)
}
fun weatherByLocation(latLong: String): LiveData<Resource<Response>> = liveData(Dispatchers.IO) {
val response = appRepository.weatherByLocation(lat?:"", long?:"")
emit(response)
}
这里我使用了三个 liveData{} 块,它们从存储库和改造中获取数据。但它们具有相同的 return 类型 LiveData<Resource<Response>>
。我可以对所有三个使用单个 liveData{} 吗?如果是,那么该怎么做?还有一个问题,使用 liveData(Dispatchers.IO) 或使用 liveData{}(没有 Dispatchers.IO)会有什么不同吗?
Using liveData(Dispatchers.IO) or using liveData{} (without Dispatchers.IO) will make any difference?
是的,默认情况下 liveData{}
构建器将在 UI(Main) 线程上调用, 但由于您已明确添加 liveData(Dispatchers.IO){}
它现在将安排在 IO 线程上。
我个人做的是,像往常一样让 liveData{}
运行 在 UI 线程上,但调用我所有的 suspend
在 IO 线程上运行,只是为了确保 emit()
操作在 UI 线程上执行,没有任何延迟。例如:
val someData = liveData{
val dataFromNetwork = getDataFromNetwork()
emit(dataFromNetwork)
}
suspend fun getDataFromNetwork() = withContext(Dispatchers.IO){
apiClient.getData()
}
Can I use single liveData{} for all three, if yes then how to do that?
好吧,这很难说,因为这是设计选择的问题,因主题而异,还取决于您如何使用所有三个函数的结果(是否按顺序调用所有三个方法或平行)。不过,我会尝试给出一个方向,
这么说吧,你想到了这样的东西,
fun getWeatherData(criteriaToGetWeatherData:String) = liveData(Dispatchers.IO){
when(criteriaToGetWeatherData){
isByCity -> {
val response = appRepository.weatherByCity(cityName)
emit(response)
}
isByZipCode -> {
val response = appRepository.weatherByZipCode(zipCode)
emit(response)
}
isByLocation -> {
val response = appRepository.weatherByLocation(lat?:"", long?:"")
emit(response)
}
}
}
您现在已将三个函数的样板代码缩减为一个函数。
但请考虑以下事项,
- 现在您的单个函数正在完成三个函数的工作。
- 你的功能已经很庞大了,未来会进一步扩展。
- 你违反了Open/Close原则,你的功能将被修改
每当未来出现新的天气标准时。
- 最糟糕的是,所有
repository
方法都是异步函数,假设在快速连续调用所有三个方法的情况下,无法保证也无法区分哪个先返回,哪个 emit()
有哪些天气数据。此外,如果您只有一个订阅者观察 getWeatherData()
,您将不知道通知您的是三种内部方法中的哪一种。
根据 Bob Martin 叔叔的 Clean Code:
Functions should do one thing. They should do it well, They should do it only.
归根结底,我们必须记住 代码可读性才是王道。所以遵循 KISS(保持简单愚蠢) 原则,我会保留这三个功能。
我的代码
fun weatherByCity(cityName: String): LiveData<Resource<Response>> = liveData(Dispatchers.IO) {
val response = appRepository.weatherByCity(cityName)
emit(response)
}
fun weatherByZipCode(zipCode: String): LiveData<Resource<Response>> = liveData(Dispatchers.IO) {
val response = appRepository.weatherByZipCode(zipCode)
emit(response)
}
fun weatherByLocation(latLong: String): LiveData<Resource<Response>> = liveData(Dispatchers.IO) {
val response = appRepository.weatherByLocation(lat?:"", long?:"")
emit(response)
}
这里我使用了三个 liveData{} 块,它们从存储库和改造中获取数据。但它们具有相同的 return 类型 LiveData<Resource<Response>>
。我可以对所有三个使用单个 liveData{} 吗?如果是,那么该怎么做?还有一个问题,使用 liveData(Dispatchers.IO) 或使用 liveData{}(没有 Dispatchers.IO)会有什么不同吗?
Using liveData(Dispatchers.IO) or using liveData{} (without Dispatchers.IO) will make any difference?
是的,默认情况下 liveData{}
构建器将在 UI(Main) 线程上调用, 但由于您已明确添加 liveData(Dispatchers.IO){}
它现在将安排在 IO 线程上。
我个人做的是,像往常一样让 liveData{}
运行 在 UI 线程上,但调用我所有的 suspend
在 IO 线程上运行,只是为了确保 emit()
操作在 UI 线程上执行,没有任何延迟。例如:
val someData = liveData{
val dataFromNetwork = getDataFromNetwork()
emit(dataFromNetwork)
}
suspend fun getDataFromNetwork() = withContext(Dispatchers.IO){
apiClient.getData()
}
Can I use single liveData{} for all three, if yes then how to do that?
好吧,这很难说,因为这是设计选择的问题,因主题而异,还取决于您如何使用所有三个函数的结果(是否按顺序调用所有三个方法或平行)。不过,我会尝试给出一个方向,
这么说吧,你想到了这样的东西,
fun getWeatherData(criteriaToGetWeatherData:String) = liveData(Dispatchers.IO){
when(criteriaToGetWeatherData){
isByCity -> {
val response = appRepository.weatherByCity(cityName)
emit(response)
}
isByZipCode -> {
val response = appRepository.weatherByZipCode(zipCode)
emit(response)
}
isByLocation -> {
val response = appRepository.weatherByLocation(lat?:"", long?:"")
emit(response)
}
}
}
您现在已将三个函数的样板代码缩减为一个函数。
但请考虑以下事项,
- 现在您的单个函数正在完成三个函数的工作。
- 你的功能已经很庞大了,未来会进一步扩展。
- 你违反了Open/Close原则,你的功能将被修改 每当未来出现新的天气标准时。
- 最糟糕的是,所有
repository
方法都是异步函数,假设在快速连续调用所有三个方法的情况下,无法保证也无法区分哪个先返回,哪个emit()
有哪些天气数据。此外,如果您只有一个订阅者观察getWeatherData()
,您将不知道通知您的是三种内部方法中的哪一种。
根据 Bob Martin 叔叔的 Clean Code:
Functions should do one thing. They should do it well, They should do it only.
归根结底,我们必须记住 代码可读性才是王道。所以遵循 KISS(保持简单愚蠢) 原则,我会保留这三个功能。