【问题标题】:Moshi JsonAdapter to handle Observable<Bitmap> in RetrofitMoshi JsonAdapter 在 Retrofit 中处理 Observable<Bitmap>
【发布时间】:2020-04-19 10:16:23
【问题描述】:

目前,我正在通过以下方式解码Bitmap

@GET("api/users/get_avatar/{userId}/default.png")
fun getAvatar(@Header("ApiToken") apiToken: String, @Path("userId") userId: String): Observable<ResponseBody>

在 ViewModel 中解码

val avatar = it()?.let { body ->
   val stream = body.byteStream()
   BitmapFactory.decodeStream(stream)
}

但是,我想使用更优雅的 Moshi JsonAdapter。

我的电话看起来像:

@GET("api/users/get_avatar/{userId}/default.png")
fun getAvatar(@Header("ApiToken") apiToken: String, @Path("userId") userId: String): Observable<Bitmap>

我正在添加适配器:

return Moshi.Builder()
        .add(BitmapAdapter())

但是,很可能我的适配器是错误的:

private class BitmapAdapter {

    @ToJson
    fun toJson(value: Bitmap): String {
        return value.encodeBase64()
    }

    @FromJson
    fun fromJson(value: String): Bitmap {
        return value.decodeBase64()
    }
}

它应该是什么样子?

【问题讨论】:

    标签: android retrofit moshi


    【解决方案1】:

    Moshi 用于解析 JSON,而不是直接解码图像。如果您想从 Retrofit 客户端获取 Bitmap,则需要将 Converter.Factory 直接提供给 Retrofit。

    例子:

    import android.graphics.Bitmap
    import android.graphics.BitmapFactory
    import okhttp3.ResponseBody
    import retrofit2.Converter
    import retrofit2.Retrofit
    import java.lang.reflect.Type
    
    class BitmapConverterFactory : Converter.Factory() {
    
        override fun responseBodyConverter(type: Type, annotations: Array<Annotation>, retrofit: Retrofit): Converter<ResponseBody, *>? {
            return if (type == Bitmap::class.java) {
                Converter<ResponseBody, Bitmap> {
                    value -> BitmapFactory.decodeStream(value.byteStream())
                }
            } else {
                null
            }
        }
    }
    

    并在您实例化改造实例的任何地方提供它:

    Retrofit.Builder()
        .baseUrl("https://myapi.com")
        .addConverterFactory(BitmapConverterFactory())
        .addConverterFactory(MoshiConverterFactory.create())
        .build()
    

    编辑:我最初在BitmapCoverterFactory 中犯了一个错误。 type的比较最初是和Bitmap::javaClass比较的,应该是Bitmap::class.java

    【讨论】:

    • 不幸的是,我在添加BitmapConverterFactory时仍然收到Caused by: java.lang.IllegalArgumentException: Platform class android.graphics.Bitmap (with no annotations) requires explicit JsonAdapter to be registered at com.squareup.moshi.ClassJsonAdapter$1.create(ClassJsonAdapter.java:60) at com.squareup.moshi.Moshi.adapter(Moshi.java:137) at com.squareup.moshi.Moshi.adapter(Moshi.java:97)
    • @qbait 顺序很重要。当您使用构建器实例化您的 Retrofit 实例时,BitmapConverterFactory 应该在 MoshiConverterFactory 之前。否则 Moshi 转换器工厂将尝试接管。
    • @qbait 我在BitmapConverterFactory也犯了错误,我在答案中更新了。
    • 完美,它适用于 2 个小的更改:Bitmap::class.java 而不是 BufferedImage::class.java,我需要向 Converter Converter&lt;ResponseBody, Bitmap&gt; 添加类型。非常感谢!
    • 对不起!我在我的机器上用纯 Kotlin(没有 Android)做一个例子,所以我使用的是 BufferedImage 而不是 Bitmap。很高兴它成功了!
    猜你喜欢
    • 2020-05-14
    • 1970-01-01
    • 2020-03-07
    • 2020-09-22
    • 2014-10-02
    • 1970-01-01
    • 2020-11-19
    • 2022-01-26
    • 2022-01-14
    相关资源
    最近更新 更多