Возврат не возвращает значение

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

Код модели представления:

    val bitmap : MutableLiveData<Bitmap> by lazy { MutableLiveData<Bitmap>() }

    fun retrive(doc_name : String,uid: String){
    viewModelScope.launch(Dispatchers.IO){
         bitmap.postValue(repository.retrive(doc_name,uid))
     }
   }

Код репозитория:

var localfile = createTempFile("tempImage", null)
var bitmap :Bitmap? = null
override suspend fun retrive(doc_name:String,uid: String)  : Bitmap?{
    val storageRef = FirebaseStorage.getInstance().reference?.child("/image/8WEFQnomCEMtlaSkCIkrBgT7XeO2/download")

    storageRef.getFile(localfile).addOnSuccessListener {
        bitmap = BitmapFactory.decodeFile(localfile.absolutePath)
    }
    return bitmap
}

Код во фрагменте внутри части View Created:

val obsover = Observer<Bitmap>{
        image.setImageBitmap(it)
    }
    admin_viewmodel.bitmap.observe(viewLifecycleOwner,obsover)

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

  1. Внутри кода репозитория, которым я поделился выше:

         return bitmap!!
    

2. Внутри кода View Model, которым я поделился выше:

bitmap.postValue(repository.retrive(doc_name,uid))

Я думаю, что его невозможно вернуть, потому что все работает в разных потоках. Пожалуйста, помогите мне решить это, спасибо.

Изменить после изменения кода ответа Broot:

override suspend fun retrive(doc_name:String,uid: String)  : Bitmap {
return suspendCoroutine { cont ->
    val storageRef =
        FirebaseStorage.getInstance().reference?.child("/image/0XhL4jD4XCemk38rcRkIEjJMgjh2/Aadhar")
    val localfile = createTempFile("tempImage", null)
    storageRef.getFile(localfile).addOnSuccessListener {
        val x = cont.resume(bitmap!!)
        Log.d("checck", "$x")
    }


}

}

Это не из-за другого потока, а потому, что вы возвращаетесь из retrive() до того, как bitmap установлен. Лямбда, переданная в addOnSuccessListener(), выполняется асинхронно, позже. Пожалуйста, прочитайте этот вопрос и особенно связанный ответ (мной): stackoverflow.com/a/69966845/448875 Кстати, это «извлечение», а не «извлечение».

broot 09.04.2022 22:17

Эй, во-первых, спасибо, я застрял на этом довольно долгое время. У меня есть код, который я настроил, может быть, вы поможете мне настроить его лучше, так как у меня все еще есть ноль, я считаю, что сделал что-то не так. Я добавлю отредактированный код под своим сообщением выше, пожалуйста, скажите, что там происходит не так.

Fawwaz Ali 10.04.2022 01:35
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
0
2
43
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш исходный код был неправильным, потому что он запускает асинхронную функцию для API, а затем немедленно возвращается, прежде чем эта асинхронная работа будет выполнена, и вызовет обратный вызов для обновления свойства bitmap.

Ваш второй код неверен, потому что он пытается возобновить продолжение со значением свойства bitmap, которое вы не обновили значением, которое было возвращено в обратном вызове. Кроме того, поскольку вам просто нужно растровое изображение из облачного файла, нет причин загружать его во временный файл. Вы можете работать напрямую с байтами. И нет причин использовать свойство, которое я вижу. bitmap может быть локальной переменной.

Кроме того, поскольку вы ничего не делаете в случае сбоя, ваша функция зависнет, если возникнет проблема с получением данных из Firebase. Ниже я просто выбрасываю ошибку, но вы можете сделать что-то другое, например, вернуть null, если хотите.

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

override suspend fun retrive(doc_name: String, uid: String): Bitmap = suspendCoroutine { cont ->
    val storageRef =
        FirebaseStorage.getInstance().reference.child("/image/0XhL4jD4XCemk38rcRkIEjJMgjh2/Aadhar")
    storageRef.getBytes(5_000_000L).addOnSuccessListener { byteArray ->
        val bitmap = BitmapFactory.decodeByteArray(byteArray)
        cont.resume(bitmap)
    }.addOnFailureListener {
        cont.resumeWithException(it)
    }
}

Однако: Firebase уже поставляется с функцией приостановки расширения await(), поэтому вам не нужно использовать suspendCoroutine.

override suspend fun retrive(doc_name: String, uid: String): Bitmap {
    val storageRef =
        FirebaseStorage.getInstance().reference.child("/image/0XhL4jD4XCemk38rcRkIEjJMgjh2/Aadhar")
    val byteArray = storageRef.getBytes(5_000_000L).await()
    return BitmapFactory.decodeByteArray(byteArray)
}

Поскольку декодирование растрового изображения — сложная операция, я бы сделал это в Dispatchers.Default:

override suspend fun retrive(doc_name: String, uid: String): Bitmap = withContext(Dispatchers.Default) {
    val storageRef =
        FirebaseStorage.getInstance().reference.child("/image/0XhL4jD4XCemk38rcRkIEjJMgjh2/Aadhar")
    val byteArray = storageRef.getBytes(5_000_000L).await()
    return BitmapFactory.decodeByteArray(byteArray)
}

Другие вопросы по теме