ASyncTask加载GridView缩略图加载最新文件两次,然后从列表顶部缓慢加载

时间:2017-06-07 12:45:23

标签: android gridview android-asynctask

我使用ASyncTask在我的GridView布局中加载缩略图,但是当我刷新数据时,缩略图以奇数顺序加载。它总是首先加载最后一个元素,但它使用第一个元素缩略图渲染它,然后使用适当的缩略图(最后的元素)重新渲染它,然后它正确加载从第一个到倒数第二个的每个其他缩略图。它还会多次重新加载图像,加载时速度相当慢(但是16mp图像)

这是我的GridView适配器(带有ASyncTask)。

public class ReceiptListAdapter extends ArrayAdapter {

    public ReceiptListAdapter(Context context, ArrayList<Receipt> receipts){
        super(context, 0, receipts);
//        getItem(1);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // Get the data item for this position
        // Check if an existing view is being reused, otherwise inflate the view
        ViewHolder holder;

        // Lookup view for data population
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.receipt_list_element, parent, false);
            holder = new ViewHolder();
            // Populate the data into the template view using the data object
            holder.title = (TextView) convertView.findViewById(R.id.TitleView);
            holder.date = (TextView) convertView.findViewById(R.id.DateView);
            holder.image = (ImageView) convertView.findViewById(R.id.containerImage);
            holder.spn = (ProgressBar) convertView.findViewById(R.id.spinner);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        Receipt receipt = (Receipt) getItem(position);
        holder.imagePath = receipt.getFilepath();
        final int tWidth = receipt.getWidth();

        // manipulate data here...
        holder.spn.setVisibility(View.VISIBLE);
        holder.image.setVisibility(View.GONE);
        holder.title.setText(receipt.getDesc());

        new AsyncTask<ViewHolder, Void, Bitmap>() {

            private ViewHolder h;

            @Override
            protected Bitmap doInBackground(ViewHolder... t) {
                h = t[0];
                Bitmap thumb = ExifUtil.rotateBitmap(h.imagePath, ThumbnailUtils.extractThumbnail(
                        BitmapFactory.decodeFile(h.imagePath),
                        tWidth,
                        tWidth));
                return thumb;
            }

            @Override
            protected void onPostExecute(Bitmap result) {
                super.onPostExecute(result);

                    h.spn.setVisibility(View.GONE);
                    h.image.setVisibility(View.VISIBLE);
                    h.image.setImageBitmap(result);

            }
        }.execute(holder);




        // Return the completed view to render on screen
        return convertView;
    }




    static class ViewHolder {
        private TextView title;
        private TextView date;
        private ImageView image;
        private String imagePath;
        private ProgressBar spn;
    }

}

3 个答案:

答案 0 :(得分:1)

我只是使用另一个库,但让我解释一些问题的来源。首先按照AsyncTask

  

首次引入时,AsyncTasks在单个后台线程上串行执行。从DONUT开始,这被改为一个线程池,允许多个任务并行运行。从HONEYCOMB开始,任务在单个线程上执行,以避免由并行执行引起的常见应用程序错误。

这意味着您一次只能加载1个缩略图。你的第二个问题是因为viewHolder实际上是重用的。您为同一视图创建2个AsyncTasks,它们在不同的时间执行(但顺序正确)。这可以通过保持对任务的引用并在创建新任务之前停止它来解决。

答案 1 :(得分:1)

  

我已用Glide库替换您的AsyncTask更新您的代码   下面

public class ReceiptListAdapter extends ArrayAdapter {

        public ReceiptListAdapter(Context context, ArrayList<Receipt> receipts){
            super(context, 0, receipts);
//        getItem(1);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // Get the data item for this position
            // Check if an existing view is being reused, otherwise inflate the view
            ViewHolder holder;

            // Lookup view for data population
            if (convertView == null) {
                convertView = LayoutInflater.from(getContext()).inflate(R.layout.receipt_list_element, parent, false);
                holder = new ViewHolder();
                // Populate the data into the template view using the data object
                holder.title = (TextView) convertView.findViewById(R.id.TitleView);
                holder.date = (TextView) convertView.findViewById(R.id.DateView);
                holder.image = (ImageView) convertView.findViewById(R.id.containerImage);
                holder.spn = (ProgressBar) convertView.findViewById(R.id.spinner);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            Receipt receipt = (Receipt) getItem(position);
            holder.imagePath = receipt.getFilepath();
            final int tWidth = receipt.getWidth();

            // manipulate data here...
            holder.spn.setVisibility(View.VISIBLE);
            holder.image.setVisibility(View.GONE);
            holder.title.setText(receipt.getDesc());

            Glide.with(context)
                    .load(holder.imagePath)
                    .into(holder.image);

            /*new AsyncTask<ViewHolder, Void, Bitmap>() {

                private ViewHolder h;

                @Override
                protected Bitmap doInBackground(ViewHolder... t) {
                    h = t[0];
                    Bitmap thumb = ExifUtil.rotateBitmap(h.imagePath, ThumbnailUtils.extractThumbnail(
                            BitmapFactory.decodeFile(h.imagePath),
                            tWidth,
                            tWidth));
                    return thumb;
                }

                @Override
                protected void onPostExecute(Bitmap result) {
                    super.onPostExecute(result);

                    h.spn.setVisibility(View.GONE);
                    h.image.setVisibility(View.VISIBLE);
                    h.image.setImageBitmap(result);

                }
            }.execute(holder);*/




            // Return the completed view to render on screen
            return convertView;
        }

        static class ViewHolder {
            private TextView title;
            private TextView date;
            private ImageView image;
            private String imagePath;
            private ProgressBar spn;
        }

    }
  

打开build.gradle并添加此依赖项

compile 'com.github.bumptech.glide:glide:4.0.0-RC0'

答案 2 :(得分:0)

我不会直接解决这个问题,而是提出两件事: 1.使用RecyclerView和RecyclerView.Adapter而不是现在拥有的。 2.使用像Picasso或Glide这样的图像加载库,而不是将其加载到AsyncTask中。在自己异步加载东西时要考虑很多事情,并且库已经处理了许多可能的错误。

在此处了解如何使用RecyclerView实现ViewHolder模式:https://guides.codepath.com/android/using-the-recyclerview