Давайте разберемся шаг за шагом о том, как LiveData
работает в вашем случае (в целом) :
- Ваш метод
downloadProfilePic()
возвращаетLiveData
из обнуляемый Bitmap
в качестве типа возврата.Метод содержит асинхронный код из addOnCompleteListener
, означающий, что его выполнение произойдет даже после того, как будет возвращено значение LiveData
.
Здесь:
fun downloadProfilePic(): LiveData<Bitmap?> {
val imageRef = storage.getReference("images/$uid/profile/profile_picture.jpg")
imageRef.getBytes(ONE_MEGABYTE).addOnCompleteListener { task ->
if (task.isSuccessful) {
//...
downloadPictureResult.value = responseBitmap
//...
} else {
downloadPictureResult.value = null
Log.d(TAG, task.exception?.localizedMessage)
}
}
return downloadPictureResult;
}
Вы возвращаете downloadPictureResult
как результат метода, который глобально инициализирован как val downloadPictureResult = MutableLiveData<Bitmap>()
изменяемые жилаты, чтобы мы могли изменить его впоследствии.И это происходит внутри обратного вызова addOnCompleteListener
.
Теперь, по-видимому, когда загружается ваше представление (Activity/Fragment)
и, следовательно, вы добавили свои текущие данные из ViewModel
как Привязка данных получает начальное значение независимо от того, что есть в LiveData
, а затем наблюдает за ним далее.
Итак, здесь вы инициализировали LiveData
с нулевым значением из Bitmap
во время этого кода val downloadPictureResult = MutableLiveData<Bitmap>()
возвращает нулевое значение для самого первого раза.
И затем происходит обратный вызов из addOnCompleteListener
метода и значенияв качестве параметра «liveata» присваивается значение downloadPictureResult.value = responseBitmap
или null в случае ошибки.
Вот почему есть два вызова для LiveData
в вашем BindingAdapter
методе setProfilePicture()
.
Примечание: Простойхак, который вы можете сделать, если не хотите, чтобы два обратных вызова делали ваш обратный вызов синхронным, а не асинхронным.