如何使用 Glide 通过 HTTP POST 方法下载图像
How to download an image using Glide via HTTP POST method
服务器提供API通过Post请求加载图片,body看起来像
{
"image_id": someId,
"session_id": "someId"
}
响应 - 流。
如何通过 HTTP POST 方法使用 Glide 下载图像?
首先你必须为上面的响应创建一个模型对象
Example :
import android.os.Parcel;
import android.os.Parcelable;
public class Movies implements Parcelable {
private String poster_path;
private String id;
public Movies() {
}
private Movies(Parcel in) {
poster_path = in.readString();
id = in.readString();
}
public static final Creator<Movies> CREATOR = new Creator<Movies>() {
@Override
public Movies createFromParcel(Parcel in) {
return new Movies(in);
}
@Override
public Movies[] newArray(int size) {
return new Movies[size];
}
};
public String getPoster_path() {
return poster_path;
}
public void setPoster_path(String poster_path) {
this.poster_path = poster_path;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(poster_path);
dest.writeString(id);
}
}
根据响应创建模型后,我们需要保存这些数据。
private void fetchTask(final String movieType) {
if (jsonObjectRequest != null) {
jsonObjectRequest.cancel();
movies.clear();
}
Uri.Builder builder = new Uri.Builder();
builder.scheme("https")
.authority("api.themoviedb.org")
.appendPath("3")
.appendPath("movie")
.appendPath(movieType)
.appendQueryParameter(MOVIE_API_KEY, MOVIE_API_VALUE);
String url = builder.build().toString();
jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray(MovieModelConstants.MOVIE_RESULTS);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
Movies data = new Movies();
data.setPoster_path(jsonObject.getString(MOVIE_POSTER_PATH));
data.setId(jsonObject.getString(MOVIE_ID));
movies.add(data);
}
moviesAdapter = new MoviesAdapter(movies);
moviesAdapter.setItemClickListener(clickListener);
recyclerViewMovies.setAdapter(moviesAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getContext(), getString(R.string.errorMessage), Toast.LENGTH_SHORT);
}
});
Volley.newRequestQueue(getContext()).add(jsonObjectRequest);
}
}
在 Adapter 中你需要根据位置加载
Picasso.with(holder.mMovieItem.getContext()).load(generateUrlForPoster(String.valueOf(data.get(position).getPoster_path()))).into(holder.mMovieItem);
Glide 中没有接收 post 请求 url 的方法。
因此,您必须使用 HTTPUrlConnection 从请求中获取 bytes[],然后使用 Glide 将此 bytes[] 加载到 imageView 中。
Glide.with(context).load(byteArr).into(imageView);
使用 Glide & Retrofit 2 通过 HTTP POST 方法加载图像的算法:
1)创建接口,所有通过HTTPPOST方式加载图片的请求都要实现该接口:
public interface CacheableRequest {
String getCacheKey();
}
2) 创建要加载的模型,它将用作 Glide.with(context).load(model):
的参数
import java.io.IOException;
import java.io.InputStream;
import okhttp3.ResponseBody;
import retrofit2.Call;
public class RetrofitStream {
private final Call<ResponseBody> call;
private final CacheableRequest request;
public RetrofitStream(Call<ResponseBody> call, CacheableRequest request) {
this.call = call;
this.request = request;
}
public InputStream getStream() throws IOException {
return call.execute().body().byteStream();
}
public String getCacheKey() {
return request.getCacheKey();
}
}
3) 创建 com.bumptech.glide.load.data.DataFetcher:
的实现
import android.support.annotation.Nullable;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.data.DataFetcher;
import java.io.IOException;
import java.io.InputStream;
public class RetrofitFetcher implements DataFetcher<InputStream> {
private final RetrofitStream retrofitStream;
private InputStream stream;
public RetrofitFetcher(RetrofitStream retrofitStream) {
this.retrofitStream = retrofitStream;
}
@Nullable
@Override
public InputStream loadData(Priority priority) throws Exception {
return stream = retrofitStream.getStream();
}
@Override
public void cleanup() {
if (stream != null) {
try {
stream.close();
} catch (IOException ignored) {
}
}
}
@Override
public String getId() {
return retrofitStream.getCacheKey();
}
@Override
public void cancel() {
}
}
4) 创建 com.bumptech.glide.load.model.ModelLoader 的实现:
import android.content.Context;
import android.support.annotation.Keep;
import android.support.annotation.Nullable;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.model.GenericLoaderFactory;
import com.bumptech.glide.load.model.ModelCache;
import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.model.ModelLoaderFactory;
import java.io.InputStream;
public class RetrofitStreamLoader implements ModelLoader<RetrofitStream, InputStream> {
private final ModelCache<RetrofitStream, RetrofitStream> modelCache;
@Keep
public RetrofitStreamLoader() {
this(null);
}
public RetrofitStreamLoader(@Nullable ModelCache<RetrofitStream, RetrofitStream> modelCache) {
this.modelCache = modelCache;
}
@Override
public DataFetcher<InputStream> getResourceFetcher(RetrofitStream model, int width, int height) {
// GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time spent parsing urls.
RetrofitStream stream = model;
if (modelCache != null) {
stream = modelCache.get(model, 0, 0);
if (stream == null) {
modelCache.put(model, 0, 0, model);
stream = model;
}
}
return new RetrofitFetcher(stream);
}
/**
* The default factory for {@link RetrofitStreamLoader}s.
*/
public static class Factory implements ModelLoaderFactory<RetrofitStream, InputStream> {
private final ModelCache<RetrofitStream, RetrofitStream> modelCache = new ModelCache<>(500);
@Override
public ModelLoader<RetrofitStream, InputStream> build(Context context, GenericLoaderFactory factories) {
return new RetrofitStreamLoader(modelCache);
}
@Override
public void teardown() {
// Do nothing.
}
}
}
5) 创建 GlideModule 的实现,允许配置 Glide
import android.content.Context;
import com.bumptech.glide.Glide;
import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory;
import com.bumptech.glide.module.GlideModule;
import java.io.InputStream;
public class RetrofitGlideModule implements GlideModule {
private final static int IMAGES_CACHE_MAX_BYTE_SIZE = 20 * 1024 * 1024;
private final static String IMAGES_CACHE_PATH = "images";
@Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, IMAGES_CACHE_PATH, IMAGES_CACHE_MAX_BYTE_SIZE))
.setDecodeFormat(DecodeFormat.PREFER_RGB_565);
}
@Override
public void registerComponents(Context context, Glide glide) {
glide.register(RetrofitStream.class, InputStream.class, new RetrofitStreamLoader.Factory());
}
}
6) 在 AndroidManifest.xml
中添加关于创建的 RetrofitGlideModule 的元数据
<application...>
<meta-data
android:name="<package>.RetrofitGlideModule"
android:value="GlideModule" />
</application>
现在可以通过以下方式下载图片:
Call<ResponseBody> call = retrofit.getImage(cacheableRequest);
Glide.with(context).load(new RetrofitStream(call, cacheableRequest)).into(imageView);
服务器提供API通过Post请求加载图片,body看起来像
{
"image_id": someId,
"session_id": "someId"
}
响应 - 流。 如何通过 HTTP POST 方法使用 Glide 下载图像?
首先你必须为上面的响应创建一个模型对象
Example :
import android.os.Parcel;
import android.os.Parcelable;
public class Movies implements Parcelable {
private String poster_path;
private String id;
public Movies() {
}
private Movies(Parcel in) {
poster_path = in.readString();
id = in.readString();
}
public static final Creator<Movies> CREATOR = new Creator<Movies>() {
@Override
public Movies createFromParcel(Parcel in) {
return new Movies(in);
}
@Override
public Movies[] newArray(int size) {
return new Movies[size];
}
};
public String getPoster_path() {
return poster_path;
}
public void setPoster_path(String poster_path) {
this.poster_path = poster_path;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(poster_path);
dest.writeString(id);
}
}
根据响应创建模型后,我们需要保存这些数据。
private void fetchTask(final String movieType) {
if (jsonObjectRequest != null) {
jsonObjectRequest.cancel();
movies.clear();
}
Uri.Builder builder = new Uri.Builder();
builder.scheme("https")
.authority("api.themoviedb.org")
.appendPath("3")
.appendPath("movie")
.appendPath(movieType)
.appendQueryParameter(MOVIE_API_KEY, MOVIE_API_VALUE);
String url = builder.build().toString();
jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray(MovieModelConstants.MOVIE_RESULTS);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
Movies data = new Movies();
data.setPoster_path(jsonObject.getString(MOVIE_POSTER_PATH));
data.setId(jsonObject.getString(MOVIE_ID));
movies.add(data);
}
moviesAdapter = new MoviesAdapter(movies);
moviesAdapter.setItemClickListener(clickListener);
recyclerViewMovies.setAdapter(moviesAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getContext(), getString(R.string.errorMessage), Toast.LENGTH_SHORT);
}
});
Volley.newRequestQueue(getContext()).add(jsonObjectRequest);
}
}
在 Adapter 中你需要根据位置加载
Picasso.with(holder.mMovieItem.getContext()).load(generateUrlForPoster(String.valueOf(data.get(position).getPoster_path()))).into(holder.mMovieItem);
Glide 中没有接收 post 请求 url 的方法。
因此,您必须使用 HTTPUrlConnection 从请求中获取 bytes[],然后使用 Glide 将此 bytes[] 加载到 imageView 中。
Glide.with(context).load(byteArr).into(imageView);
使用 Glide & Retrofit 2 通过 HTTP POST 方法加载图像的算法:
1)创建接口,所有通过HTTPPOST方式加载图片的请求都要实现该接口:
public interface CacheableRequest {
String getCacheKey();
}
2) 创建要加载的模型,它将用作 Glide.with(context).load(model):
的参数import java.io.IOException;
import java.io.InputStream;
import okhttp3.ResponseBody;
import retrofit2.Call;
public class RetrofitStream {
private final Call<ResponseBody> call;
private final CacheableRequest request;
public RetrofitStream(Call<ResponseBody> call, CacheableRequest request) {
this.call = call;
this.request = request;
}
public InputStream getStream() throws IOException {
return call.execute().body().byteStream();
}
public String getCacheKey() {
return request.getCacheKey();
}
}
3) 创建 com.bumptech.glide.load.data.DataFetcher:
的实现import android.support.annotation.Nullable;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.data.DataFetcher;
import java.io.IOException;
import java.io.InputStream;
public class RetrofitFetcher implements DataFetcher<InputStream> {
private final RetrofitStream retrofitStream;
private InputStream stream;
public RetrofitFetcher(RetrofitStream retrofitStream) {
this.retrofitStream = retrofitStream;
}
@Nullable
@Override
public InputStream loadData(Priority priority) throws Exception {
return stream = retrofitStream.getStream();
}
@Override
public void cleanup() {
if (stream != null) {
try {
stream.close();
} catch (IOException ignored) {
}
}
}
@Override
public String getId() {
return retrofitStream.getCacheKey();
}
@Override
public void cancel() {
}
}
4) 创建 com.bumptech.glide.load.model.ModelLoader 的实现:
import android.content.Context;
import android.support.annotation.Keep;
import android.support.annotation.Nullable;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.model.GenericLoaderFactory;
import com.bumptech.glide.load.model.ModelCache;
import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.model.ModelLoaderFactory;
import java.io.InputStream;
public class RetrofitStreamLoader implements ModelLoader<RetrofitStream, InputStream> {
private final ModelCache<RetrofitStream, RetrofitStream> modelCache;
@Keep
public RetrofitStreamLoader() {
this(null);
}
public RetrofitStreamLoader(@Nullable ModelCache<RetrofitStream, RetrofitStream> modelCache) {
this.modelCache = modelCache;
}
@Override
public DataFetcher<InputStream> getResourceFetcher(RetrofitStream model, int width, int height) {
// GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time spent parsing urls.
RetrofitStream stream = model;
if (modelCache != null) {
stream = modelCache.get(model, 0, 0);
if (stream == null) {
modelCache.put(model, 0, 0, model);
stream = model;
}
}
return new RetrofitFetcher(stream);
}
/**
* The default factory for {@link RetrofitStreamLoader}s.
*/
public static class Factory implements ModelLoaderFactory<RetrofitStream, InputStream> {
private final ModelCache<RetrofitStream, RetrofitStream> modelCache = new ModelCache<>(500);
@Override
public ModelLoader<RetrofitStream, InputStream> build(Context context, GenericLoaderFactory factories) {
return new RetrofitStreamLoader(modelCache);
}
@Override
public void teardown() {
// Do nothing.
}
}
}
5) 创建 GlideModule 的实现,允许配置 Glide
import android.content.Context;
import com.bumptech.glide.Glide;
import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory;
import com.bumptech.glide.module.GlideModule;
import java.io.InputStream;
public class RetrofitGlideModule implements GlideModule {
private final static int IMAGES_CACHE_MAX_BYTE_SIZE = 20 * 1024 * 1024;
private final static String IMAGES_CACHE_PATH = "images";
@Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, IMAGES_CACHE_PATH, IMAGES_CACHE_MAX_BYTE_SIZE))
.setDecodeFormat(DecodeFormat.PREFER_RGB_565);
}
@Override
public void registerComponents(Context context, Glide glide) {
glide.register(RetrofitStream.class, InputStream.class, new RetrofitStreamLoader.Factory());
}
}
6) 在 AndroidManifest.xml
中添加关于创建的 RetrofitGlideModule 的元数据<application...>
<meta-data
android:name="<package>.RetrofitGlideModule"
android:value="GlideModule" />
</application>
现在可以通过以下方式下载图片:
Call<ResponseBody> call = retrofit.getImage(cacheableRequest);
Glide.with(context).load(new RetrofitStream(call, cacheableRequest)).into(imageView);