How to download an image using Glide via HTTP POST method
Asked Answered
C

3

8

Server provides the API to load image through Post request, whose body looks like

{
 "image_id": someId,
 "session_id": "someId"
}
Response - stream.
How to download an image using Glide via HTTP POST method?
Centro answered 27/12, 2016 at 9:23 Comment(2)
what is image id?Conchoidal
ideally server must send the image url as GET request, and then you have to pass that url to Glide. hoping that you are using Volley to make the request, your app performance will be improved if you use two asymchronous requests one for content and another for imageConchoidal
C
4

Algorithm for loading images using Glide & Retrofit 2 via HTTP POST method:

1) Create interface, which should be implemented by all requests for image loading via HTTP POST method:

public interface CacheableRequest {
    String getCacheKey();
}

2) Create model to load, which will be used as a parameter for 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) Create an implementation of 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) Create an implementation of 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) Create an implementation of GlideModule, which allows configure 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) Add meta data about created RetrofitGlideModule in AndroidManifest.xml

<application...>
<meta-data
        android:name="<package>.RetrofitGlideModule"
        android:value="GlideModule" />
</application>

Now you can download images next way:

Call<ResponseBody> call = retrofit.getImage(cacheableRequest);
Glide.with(context).load(new RetrofitStream(call, cacheableRequest)).into(imageView);
Centro answered 16/2, 2018 at 13:57 Comment(0)
V
0

First you have to create a Model Object for the above response

    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);
        }
    }

Once Model is create from the response we need to save those data.

   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);
        }
    }

In the Adapter you need load based on the position

Picasso.with(holder.mMovieItem.getContext()).load(generateUrlForPoster(String.valueOf(data.get(position).getPoster_path()))).into(holder.mMovieItem);
Vo answered 27/12, 2016 at 9:49 Comment(0)
D
-1

There is no such method in Glide which receive post request url.

So all you have to get bytes[] from request using HTTPUrlConnection and then load this bytes[] into imageView using Glide.

 Glide.with(context).load(byteArr).into(imageView);
Demission answered 27/12, 2016 at 10:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.