改造API以检索png图像

Pra*_* CR 28 android retrofit

嗨,我是Android的Retrofit框架的新手.我可以使用它从REST服务获得JSON响应,但我不知道如何使用改造下载png.我想从这个网址下载png:http: //wwwns.akamai.com/media_resources/globe_emea.png.什么应该响应要在Callback <>中指定的对象来实现这一点.

Mig*_*gne 34

如上所述,您不应该使用Retrofit实际下载图像本身.如果您的目标是简单地下载内容而不显示内容,那么您可以简单地使用像OkHttp这样的Http客户端,这是Square的另一个库.

这里有几行代码可以让你下载这个图像.然后,您可以从InputStream中读取数据.

    OkHttpClient client = new OkHttpClient();

    Request request = new Request.Builder()
            .url("http://wwwns.akamai.com/media_resources/globe_emea.png")
            .build();

    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Request request, IOException e) {
            System.out.println("request failed: " + e.getMessage());
        }

        @Override
        public void onResponse(Response response) throws IOException {
            response.body().byteStream(); // Read the data from the stream
        }
    });
Run Code Online (Sandbox Code Playgroud)

即使Retrofit不是工作人员回答你的问题,你的接口定义的签名也会这样.但是再次不要这样做.

public interface Api {
    @GET("/media_resources/{imageName}")
    void getImage(@Path("imageName") String imageName, Callback<Response> callback);
}
Run Code Online (Sandbox Code Playgroud)

  • 该帖子提到,只有当您只是下载内容但未显示内容时,这才是替代方案.Pradeem的用例没有具体指明他想要显示内容. (2认同)

Spa*_*Bao 31

当然我们通常使用Picasso来加载图像,但有时我们确实需要使用Retrofit来加载特殊图像(比如获取验证码图像),你需要为请求添加一些标题,从响应的标题中获取一些值(当然你可以也使用Picasso + OkHttp,但在一个项目中你已经使用Retrofit来处理大多数网络请求),所以这里介绍如何通过Retrofit 2.0.0实现(我已经在我的项目中实现).

关键是你需要okhttp3.ResponseBody用来接收响应,否则Retrofit会将响应数据解析为JSON,而不是二进制数据.

代码:

public interface Api {
    // don't need add 'Content-Type' header, it's useless
    // @Headers({"Content-Type: image/png"})
    @GET
    Call<ResponseBody> fetchCaptcha(@Url String url);
}

Call<ResponseBody> call = api.fetchCaptcha(url);
call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if (response.isSuccessful()) {
                if (response.body() != null) {
                    // display the image data in a ImageView or save it
                    Bitmap bmp = BitmapFactory.decodeStream(response.body().byteStream());
                    imageView.setImageBitmap(bmp);
                } else {
                    // TODO
                }
            } else {
                // TODO
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            // TODO
        }
    });
Run Code Online (Sandbox Code Playgroud)


Yur*_*raj 15

Retrofit是一个REST库,你只能使用Retrofit来获取图像URL但是为了显示Image你应该使用Picasso:http://square.github.io/picasso/

  • 非常感谢建议毕加索,它很容易使用库. (2认同)

Alé*_*lho 11

声明它返回Call for instance:

@GET("/api/{api}/bla/image.png")
Call<ResponseBody> retrieveImageData();
Run Code Online (Sandbox Code Playgroud)

然后自己将其转换为Bitmap:

ResponseBody body = retrofitService.retrieveImageData().execute().body();
        byte[] bytes = body.bytes();
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Run Code Online (Sandbox Code Playgroud)


Vas*_*huk 6

细节

  • 安卓工作室3.1.4
  • 科特林 1.2.60
  • 改造2.4.0
  • 检查了 minSdkVersion 19

解决方案

对象改造图像

object RetrofitImage {

    private fun provideRetrofit(): Retrofit {
        return Retrofit.Builder().baseUrl("https://google.com").build()
    }

    private interface API {
        @GET
        fun getImageData(@Url url: String): Call<ResponseBody>
    }

    private val api : API by lazy  { provideRetrofit().create(API::class.java) }

    fun getBitmapFrom(url: String, onComplete: (Bitmap?) -> Unit) {

        api.getImageData(url).enqueue(object : retrofit2.Callback<ResponseBody> {

            override fun onFailure(call: Call<ResponseBody>?, t: Throwable?) {
                onComplete(null)
            }

            override fun onResponse(call: Call<ResponseBody>?, response: Response<ResponseBody>?) {
                if (response == null || !response.isSuccessful || response.body() == null || response.errorBody() != null) {
                    onComplete(null)
                    return
                }
                val bytes = response.body()!!.bytes()
                onComplete(BitmapFactory.decodeByteArray(bytes, 0, bytes.size))
            }
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

用法1

RetrofitImage.getBitmapFrom(ANY_URL_STRING) {
   // "it" - your bitmap
   print("$it")
}
Run Code Online (Sandbox Code Playgroud)

用法2

ImageView 的扩展

fun ImageView.setBitmapFrom(url: String) {
    val imageView = this
    RetrofitImage.getBitmapFrom(url) {
        val bitmap: Bitmap?
        bitmap = if (it != null) it else {
            // create empty bitmap
            val w = 1
            val h = 1
            val conf = Bitmap.Config.ARGB_8888
            Bitmap.createBitmap(w, h, conf)
        }

        Looper.getMainLooper().run {
            imageView.setImageBitmap(bitmap!!)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

扩展的使用

imageView?.setBitmapFrom(ANY_URL_STRING)
Run Code Online (Sandbox Code Playgroud)