Reputation: 513
i'm actually working in an Android app who need to downloading PNG from web and showing it in a recyclerView. The downloading part works fine same as the save in the internal storage. The problem is with the display, when i load it in AsyncTask in my onBindViewHolder, this isn't fluid..... and on AVD i have an exception something like resources not closed. So i will paste the adapter :
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{
private static final String TAG = "MyAdapter";
private List<Item> listItem = null;
public MyAdapter(List<Item> listItem) {
this.listItem = listItem;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Log.d(logTag, "view group " + parent);
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row, parent, false);
return new MyViewHolder(v);
}
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
//Log.d(logTag, " bind " + position + " holder " + holder);
final Item item = listItem.get(position);
holder.position = position;
//new LoadBitmap(position, holder).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, item.getId());
}
private class LoadBitmap extends AsyncTask<String, Void, Bitmap> {
private MyViewHolder holder = null;
private int position = 0;
public LoadBitmap(int position, MyViewHolder holder) {
this.holder = holder;
this.position = position;
}
@Override
protected Bitmap doInBackground(String... params) {
File file = new File("/data/data/myapp/files", params[0]);
FileInputStream fis = null;
Bitmap bitmap = null;
try {
fis = new FileInputStream(file);
bitmap = BitmapFactory.decodeStream(fis);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null && holder.position == position) {
holder.imageView.setImageBitmap(bitmap);
}
}
}
@Override
public int getItemCount() {
return listItem.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private ImageView imageView = null;
int position = 0;
public MyViewHolder(View itemView) {
super(itemView);
imageView = (ImageView) itemView.findViewById(R.id.imageView_item);
}
}
}
I try too with UI Thread :
holder.imageView.post(new Runnable() {
@Override
public void run() {
File file = new File("/data/data/myapp/files", item.getId());
FileInputStream fis = null;
Bitmap bitmap = null;
try {
fis = new FileInputStream(file);
bitmap = BitmapFactory.decodeStream(fis);
holder.imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
});
I hope it's clear enough and sorry for my english. Thanx.
EDIT : This fix work perfect
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
Item item = listItem.get(position);
holder.position = position;
File file = new File("/data/data/myApp/files", item.getId());
Picasso.with(holder.itemView.getContext()).load(file).resize(50,25).centerCrop().into(holder.imageView);
}
Upvotes: 1
Views: 5619
Reputation: 2713
Why not use Picasso or a library for that?
It's as easy as:
Uri uri = Uri.fromFile(yourFilePath);
Picasso.with(activity).load(uri)
.resize(100, 100).centerCrop().into(viewHolder.imageView);
Or load the image in the onCreateViewHolder method
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Log.d(logTag, "view group " + parent);
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row, parent, false);
ImageView imgView = v.findViewById(R.id.yourId);
final int position = holder.getAdapterPosition(); //get your item with position
new LoadBitmap( ...)
return new MyViewHolder(v);
}
and do not forget to recycle your bitmap with bitmap.recycle()
But never start async tasks in onBindViewHolder.
EDIT: You can get the item with: final int position = holder.getAdapterPosition();
Upvotes: 1
Reputation: 627
Don't ever use AsyncTasks
for loading any kind data into RecyclerView
or ListView
.
Check out Picasso and use this construction
File file = new File(path);
Picasso.with(context).load(file).placeholder(placeholderResId).into(imageView);
to load from disk.
Upvotes: 1