Reputation: 452
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
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