首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Retrofit2 + RxJava 請求網絡圖片:解決 MalformedJsonException 與 ResponseBody 轉換失敗

     編輯:程式設計疑難解答

問題現象

使用 Retrofit2 + RxJava 請求圖片 URL 時拋出異常:

com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $

原因很明顯:服務器返回的是二進制圖片數據(JPG),而非 JSON。但 Retrofit 默認配置了 GsonConverterFactory,會嘗試將響應體解析為 JSON,導致解析失敗。

根本原因分析

  1. 接口定義錯誤:Observable<ResponseBody> getImg(@Url String url) 返回類型應為 ResponseBody 或 byte[],而非泛型未指定的 Observable。
  2. 轉換器衝突:GsonConverterFactory 會攔截所有響應並嘗試 JSON 解析,圖片二進制數據無法解析。
  3. OkHttp 版本不匹配:錯誤日誌提示 okhttp3.ResponseBody 與 okhttp.ResponseBody(2.x 版本)轉換失敗,說明依賴版本衝突。

正確解決方案

方案一:移除 GsonConverter,使用內置 ResponseBody 轉換器(推薦)

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://pic41.nipic.com/")
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 注意 RxJava 2.x 用法
    // .addConverterFactory(GsonConverterFactory.create()) // 刪除這行!
    .build();

ImgService service = retrofit.create(ImgService.class);
service.getImg("https://pic41.nipic.com/20140509/4746986_145156378323_2.jpg")
    .subscribeOn(Schedulers.io())
    .map(responseBody -> {
        // 直接處理字節流
        return BitmapFactory.decodeStream(responseBody.byteStream());
    })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(bitmap -> imageView.setImageBitmap(bitmap),
               throwable -> throwable.printStackTrace());

方案二:自定義 Converter 處理二進制數據(兼容舊版本)

.addConverterFactory(new Converter.Factory() {
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        return new Converter<ResponseBody, ResponseBody>() {
            @Override
            public ResponseBody convert(ResponseBody value) throws IOException {
                return value; // 直接透傳
            }
        };
    }
})

接口正確定義

public interface ImgService {
    @GET
    Observable<ResponseBody> getImg(@Url String url); // 必須指定泛型
}

依賴版本檢查

確保 build.gradle 中 OkHttp、Retrofit、RxJava 版本一致:

implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'

總結

請求圖片/文件時:不要添加 GsonConverterFactory,直接使用 ResponseBody 或 byte[] 作為返回類型,Retrofit 內置轉換器會自動處理二進制數據。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved