FlyingNades
FlyingNades

Reputation: 452

loading images to a recyclerview using a thread

So I have a Recyclerview which holding items with images, I want to load images into the items but when I do that I got a lot of fps drops. I read that I need to use another thread for the network part and I tried to do that as you can see, and it seems good to me but I can't figure out how to stop the fps drops and make the scrolling in the Recyclerview smooth, this Recyclerview supposed to hold between 10 and 100. Am I supposed to run the activity in a thread?
Note: The fps drops occur with 10 items.

calling to the HttpWrapper.LoadImageFromWebOperations function in OnBindViewHolder.

HomeAdapter.java

public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.HomeViewHolder>{

private Context context;
private ArrayList<RecipeModel> items;

public HomeAdapter(Context context, ArrayList<RecipeModel> items) {
    this.context = context;
    this.items = items;
}

@Override
public HomeAdapter.HomeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(context);
    View v = inflater.inflate(R.layout.home_item,null);
    HomeAdapter.HomeViewHolder holder = new HomeAdapter.HomeViewHolder(v);
    return holder;
}

public void addItem(RecipeModel item){
    this.items.add(item);
    notifyDataSetChanged();
}

@Override
public void onBindViewHolder(HomeAdapter.HomeViewHolder holder, final int position) {
    RecipeModel model = items.get(position);
    holder.name.setText(model.getName());
    holder.directions.setText(model.getDirections()[0]);
    Drawable drawable = HttpWrapper.LoadImageFromWebOperations(model.getImageSource());
    holder.image.setImageDrawable(drawable);
}

@Override
public int getItemCount() {
    return items.size();
}

class HomeViewHolder extends RecyclerView.ViewHolder{
    TextView name;
    TextView directions;
    ImageView image;

    public HomeViewHolder(View itemView) {
        super(itemView);
        name = (TextView) itemView.findViewById(R.id.recipe_name);
        directions = (TextView) itemView.findViewById(R.id.recipe_directions);
        image = (ImageView) itemView.findViewById(R.id.recipe_image);
    }
}

HttpWrapper.java

public class HttpWrapper {

String responseMsg = "";
private OkHttpClient client;
private Request request;
public static final String base_url = "http://kingtimmy.pythonanywhere.com";
public static final String home_route = "/home/";
public HttpWrapper() {
    client = new OkHttpClient();
}
public ArrayList<RecipeModel> get_home_recipes(int recipe_num){
    ArrayList<RecipeModel> models = new ArrayList<RecipeModel>();
    request = new Request.Builder().url(base_url + home_route + String.valueOf(recipe_num)).build();
    responseMsg = "";
    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            responseMsg = "Error: " + e.getMessage();
        }
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            responseMsg = response.body().string();
        }
    });
    while(responseMsg.equals("")){
        continue;
    }
    String[] jsons = responseMsg.split("]-]");
    for (int i = 0; i < jsons.length; i++){
        models.add(makeRecipeModel(jsons[i]));
    }
    return models;
}
public RecipeModel makeRecipeModel(String msg){
    JSONObject nodeRoot = null;
    RecipeModel model;
    try {
        nodeRoot = new JSONObject(msg);
        String[] directions = nodeRoot.get("directions").toString().split("\\n");
        String[] ingredients = nodeRoot.get("ingredients").toString().split("\\n");
        String image_source = nodeRoot.get("image").toString();
        String source_url = nodeRoot.get("source_url").toString();
        String name = nodeRoot.get("name").toString();
        int id = Integer.valueOf(nodeRoot.get("id").toString());
        model = new RecipeModel(directions,ingredients,image_source,source_url,name,id);

    } catch (JSONException e) {
        model = null;
    }
    return model;
}
public static Drawable LoadImageFromWebOperations(final String url) {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Callable<Drawable> callable = new Callable<Drawable>() {
        @Override
        public Drawable call() {
            try {
                InputStream is = (InputStream) new URL(url).getContent();
                Drawable d = Drawable.createFromStream(is, "src name");
                return d;
            } catch (Exception e) {
                System.out.println("Exc=" + e);
                return null;
            }
        }
    };
    Future<Drawable> future = executor.submit(callable);
    // future.get() returns 2 or raises an exception if the thread dies, so safer
    try {
        Drawable d = future.get();
        executor.shutdown();
        return d;
    } catch (Exception e) {
        return null;
    }
}

What am I doing wrong?

Upvotes: 1

Views: 1135

Answers (1)

Kartik Arora
Kartik Arora

Reputation: 571

Instead of writing your own thread and code to fetch, parse, decode and load the image, give Glide a try. It does all that for you with a simple single line code and loads the image in your ImageView

Upvotes: 3

Related Questions