【问题标题】:Load bitmap in recyclerView from internalStorage with Asynctask使用 Asynctask 从 internalStorage 加载 recyclerView 中的位图
【发布时间】:2015-06-25 15:50:27
【问题描述】:

我实际上在一个 Android 应用程序中工作,需要从网络下载 PNG 并将其显示在 recyclerView 中。下载部分与内部存储中的保存相同。问题出在显示器上,当我在我的 onBindViewHolder 中的 AsyncTask 中加载它时,这不是流畅的.....并且在 AVD 上我有一个异常,比如资源未关闭。所以我将粘贴适配器:

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

}

我也尝试使用 UI 线程:

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

我希望它足够清楚,对不起我的英语。 谢谢。

编辑: 此修复工作完美

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

【问题讨论】:

  • 坏主意(即使是中级)....使用一些库....所有这些回收都不是那么容易(取消上一个请求)

标签: android bitmap android-asynctask adapter android-recyclerview


【解决方案1】:

为什么不使用Picasso 或库呢?

很简单:

Uri uri = Uri.fromFile(yourFilePath);

Picasso.with(activity).load(uri)
            .resize(100, 100).centerCrop().into(viewHolder.imageView);

或者在onCreateViewHolder方法中加载图片

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

别忘了用 bitmap.recycle() 回收你的位图

但永远不要在 onBindViewHolder 中启动异步任务。

编辑: 您可以通过以下方式获取该项目: 最终 int 位置 = holder.getAdapterPosition();

【讨论】:

  • bitmap.recycle() 怎么用?
  • 我无法在 onCreateViewHolder 中执行此操作,我不知道该项目。
  • getAdapterPosition 在 onCreateViewHolder() 和 onBindViewHolder() 中总是返回 -1 我没有访问上下文的权限,我可以将它存储在构造函数中,但我担心在我的适配器中保留引用.. ...我是对的?
  • 在onCreateViewHolder()中不能调用holder
  • 您不应该在 onCreateViewHolder 中进行加载。在 onBindViewHolder 中使用它。您应该在 onCreateViewHolder 中添加的唯一内容是初始化
【解决方案2】:

永远不要使用AsyncTasks 将任何类型的数据加载到RecyclerViewListView

查看Picasso 并使用此构造

File file = new File(path);
Picasso.with(context).load(file).placeholder(placeholderResId).into(imageView);

从磁盘加载。

【讨论】:

  • 感谢这个库。我见过她使用缓存系统。它是如何工作的?如果我下次从 web 加载 png 如果我没有互联网也会从缓存中加载 png?
  • 因为我有近 100 个带有 url 的项目,并且应用程序需要在没有互联网的情况下工作。
  • 您无法确定所有图片都已缓存,因此请自行缓存。但是使用 picasso 将它们加载到图像视图中以避免内存不足错误
  • 根据官网square.github.io/picassopicasso自动进行缓存。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-20
  • 2012-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-18
相关资源
最近更新 更多