Использование компилятора liveData {} в потоке Dispatchers.IO - PullRequest
0 голосов
/ 14 марта 2020

Мой код

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 {}, которые они получают из репозитория и модифицируют. Но они имеют одинаковый тип возврата LiveData<Resource<Response>>. Могу ли я использовать один liveData {} для всех трех, если да, то как это сделать? Еще один вопрос, использование liveData (Dispatchers.IO) или использование liveData {} (без Dispatchers.IO), будет иметь какое-либо значение?

1 Ответ

1 голос
/ 14 марта 2020

Использование liveData (Dispatchers.IO) или использование liveData {} (без Dispatchers.IO) будет иметь какое-либо значение?

Да, по умолчанию * Построитель 1007 * будет вызываться в потоке 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()
     }

Могу ли я использовать один liveData {} для всех трех, если да, то как это сделать?

Хорошо Трудно сказать это, потому что это вопрос выбора дизайна, который будет варьироваться от предмета к предмету, а также зависит от того, как вы потребляете результаты от всех трех функций (независимо от того, вызываются ли все три метода последовательно или параллельно). Тем не менее, я попытаюсь дать направление,

Итак, скажем, вы придумали что-то вроде этого,

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)

                   }

      }

}

Вы теперь сократили шаблонный код трех функций до одиночная функция.

Но учтите следующее:

  1. Теперь ваша единственная функция выполняет три функции.
  2. Ваша функция уже велика в будущем область дальнейшего расширения.
  3. Вы нарушили принцип Open / Close, ваша функция будет изменена всякий раз, когда в будущем появится новый критерий погоды.
  4. Худшее, все методы repository асинхронные функции, в случае, если все три вызваны в быстрой последовательности, нет гарантии и нет способа определить, какая из них вернулась первой, а какая emit() имеет данные о погоде. Кроме того, если у вас есть только один подписчик, наблюдающий getWeatherData(), вы не будете иметь ни малейшего представления, для какого из трех внутренних методов вы были уведомлены.

Согласно «Чистому коду» дяди Боба Мартина:

Функции должны выполнять одну функцию. Они должны делать это хорошо, Они должны делать это только.

В конце концов, мы должны помнить, что читаемость кода является окончательным королем . Поэтому, следуя принципу KISS (пусть это будет просто глупо) , я бы оставил эти три функции такими, какие они есть.

...