Timo
Timo

Reputation: 513

Load bitmap in recyclerView from internalStorage with Asynctask

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

Answers (2)

Fabian
Fabian

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

Konstantin Kiriushyn
Konstantin Kiriushyn

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

Related Questions