Android中使用Retrofit2下载带授权图片(无BaseURL场景)
解决Retrofit无BaseUrl下载带授权图片的问题
核心思路
Retrofit要求BaseUrl必须是合法格式,但只要用占位式的合法BaseUrl,配合@Url注解传入完整图片链接,Retrofit会自动忽略BaseUrl,直接使用你传入的完整链接发起请求。
修改后的代码实现
1. 构建Retrofit实例
随便找一个合法的HTTP/HTTPS地址当占位BaseUrl就行,不需要和图片域名一致:
// 不需要GsonConverterFactory,因为我们直接返回ResponseBody,无需解析成对象 OkHttpClient client = new OkHttpClient.Builder().build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://placeholder.com/") // 占位用的合法BaseUrl .client(client) .build();
2. 接口写法(两种可选)
- 原写法(保留传参):
@GET Call<ResponseBody> getImage(@Url String url, @Header("Authorization") String token);
- 优化写法(推荐):用OkHttp拦截器统一添加授权头,不用每次调用都传:
// 先给OkHttpClient加拦截器 OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(chain -> { Request original = chain.request(); Request authorizedRequest = original.newBuilder() .header("Authorization", "Bearer " + yourToken) .build(); return chain.proceed(authorizedRequest); }) .build(); // 此时接口可以简化成: @GET Call<ResponseBody> getImage(@Url String url);
3. 调用并处理图片响应
拿到ResponseBody后,转成Bitmap显示或保存到本地:
IService service = retrofit.create(IService.class); // 直接传入完整的图片链接 Call<ResponseBody> call = service.getImage("https://your-full-image-url.com/image.jpg"); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if (response.isSuccessful() && response.body() != null) { // 转Bitmap显示到ImageView InputStream inputStream = response.body().byteStream(); Bitmap bitmap = BitmapFactory.decodeStream(inputStream); if (bitmap != null) { yourImageView.setImageBitmap(bitmap); } // 或者保存到本地文件 try (FileOutputStream fos = new FileOutputStream(new File(getExternalFilesDir(null), "downloaded.jpg"))) { byte[] buffer = new byte[1024]; int len; while ((len = inputStream.read(buffer)) != -1) { fos.write(buffer, 0, len); } } catch (IOException e) { e.printStackTrace(); } // 关闭流避免内存泄漏 try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } else { Log.d(TAG, "请求失败,状态码:" + response.code()); // 比如401就是授权无效,检查Token } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { Log.d(TAG, "请求出错:" + t.getMessage()); } });
关键原理说明
Retrofit的@Url注解如果传入完整的HTTP/HTTPS链接,会完全覆盖BaseUrl,直接使用该链接发起请求。所以只要BaseUrl是合法格式(带http/https和结尾斜杠),哪怕是占位的也不会影响实际请求。
内容的提问来源于stack exchange,提问作者Prasath S
相关产品推荐
相关产品推荐

