viewModel加载网络图片

添加coil库,在MainActivity中加载图片,简单好用

img


然后我是想通过viewModel来更新图片的,但没法在viewModel中使用load(),请教正确的用法

img


MainViewModel.kt

package com.example.retrofittest

import android.content.res.Resources
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.switchMap

class MainViewModel : ViewModel() {

    val imageId: LiveData<Resources>
        get() = _imageId

    private val _imageId = MutableLiveData<Resources>()

  //  load()爆红了
    init {
        _imageId.value = load("http://pic-bucket.ws.126.net/photo/0010/2022-11-22/HMP3UMG2POUR0010NOS.png")
    }

}

如果没法像MainActivity中那样使用load()的话,那只能改用retrofit访问使用了.但是我在viewModel中不知道该怎么写具体的代码.

img


图片的数据模型 ImageResponse.kt, image: Resources用这个参数对了吗?

package com.example.retrofittest

import android.content.res.Resources

data class ImageResponse(val image: Resources)

访问接口 ImageService.kt

package com.example.retrofittest

import retrofit2.Call
import retrofit2.http.GET

interface ImageService {
    @GET("photo/0010/2022-11-22/HMP3UMG2POUR0010NOS.png")
    fun getImageData(): Call<ImageResponse>
}

retrofit构建器 ServiceCreator.kt

import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object ServiceCreator {
    private const val BASE_URL = "http://pic-bucket.ws.126.net/"

    private val retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    fun <T> create(serviceClass: Class<T>): T = retrofit.create(serviceClass)
    inline fun <reified T> create(): T = create(T::class.java)
}

统一网络数据访问入口 AppNetwork.kt

import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

object AppNetwork {

    private val imageService = ServiceCreator.create<ImageService>()
    suspend fun imageApp() = imageService.getImageData().await()

    private suspend fun <T> Call<T>.await(): T {
        return suspendCoroutine { continuation ->
            enqueue(object : Callback<T> {
                override fun onResponse(call: Call<T>, response: Response<T>) {
                    val body = response.body()
                    if (body != null) continuation.resume(body)
                    else continuation.resumeWithException(
                        RuntimeException("response body is null")
                    )
                }

                override fun onFailure(call: Call<T>, t: Throwable) {
                    continuation.resumeWithException(t)
                }
            })
        }
    }
}

仓库层的统一封装入口

import androidx.lifecycle.liveData
import kotlinx.coroutines.Dispatchers

// 定义仓库层的统一封装入口  Repository.kt
object Repository {

    fun imageApp() = liveData(Dispatchers.IO) {
        val result = try {
            val imagerResponse = AppNetwork.imageApp()
            val images = imagerResponse.image
            Result.success(images)
        } catch (e: Exception) {
            Result.failure<ImageResponse>(e)
        }
        emit(result)
    }
}

在你的情况下,你应该在ViewModel中处理数据加载,然后在Activity或者Fragment中处理数据的显示。你不能在ViewModel中直接使用Coil的load()方法,因为这个方法是用来在View中加载图片的,而ViewModel不应该直接与View交互。

你可以在ViewModel中使用Retrofit或者其他网络库来加载图片数据,然后将这个数据暴露给Activity或者Fragment。然后,在Activity或者Fragment中,你可以使用Coil的load()方法来加载这个数据。

你的ImageResponse类应该包含一个表示图片URL的字符串字段,而不是一个Resources对象。你可以像下面这样修改你的ImageResponse类:

data class ImageResponse(val imageUrl: String)

然后,你可以在你的ViewModel中使用Retrofit来加载这个ImageResponse对象,然后将imageUrl字段暴露给Activity或者Fragment:

class MainViewModel : ViewModel() {
 
    val imageUrl: LiveData<String>
        get() = _imageUrl
 
    private val _imageUrl = MutableLiveData<String>()
 
    init {
        // 使用Retrofit加载图片数据
        // 假设你已经在其他地方定义了一个Retrofit的实例和一个ImageService的实例
        val call = imageService.getImageData()
        call.enqueue(object : Callback<ImageResponse> {
            override fun onResponse(call: Call<ImageResponse>, response: Response<ImageResponse>) {
                if (response.isSuccessful) {
                    val imageResponse = response.body()
                    if (imageResponse != null) {
                        _imageUrl.value = imageResponse.imageUrl
                    }
                }
            }
 
            override fun onFailure(call: Call<ImageResponse>, t: Throwable) {
                // 处理错误
            }
        })
    }
}

然后,在你的Activity或者Fragment中,你可以观察这个imageUrl字段,并使用Coil的load()方法来加载图片:

viewModel.imageUrl.observe(this, Observer { imageUrl ->
    imageView.load(imageUrl)
})

这样,你就可以在ViewModel中处理数据加载,然后在Activity或者Fragment中处理数据的显示了。

您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!
PS:问答VIP年卡 【限时加赠:IT技术图书免费领】,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632