【问题标题】:Lazy Loading in ListView with Image. (Cursor Adapter)使用图像在 ListView 中延迟加载。 (光标适配器)
【发布时间】:2015-10-12 01:53:54
【问题描述】:

我有一个列表视图,它显示带有缩略图的视频,我正在使用光标适配器(使用 ContentProvider 获取)。问题是随着列表项数量的增加,列表视图性能变得非常差。请告诉我使其延迟加载的最佳方法。

新: 我终于找到了一些解决方案。它对我来说工作正常。如果您有任何建议,请告诉我。 我的新代码在这里。 (它使用堆栈与生产者消费者模式和免费线程进行处理)

@覆盖 public void bindView(View view, Context context, Cursor cursor) {

    ViewHolder holder = (ViewHolder) view.getTag();
    String name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE));
    int id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID));
    holder.getIdView().setText(name);
    holder.getThumbView().setTag((Integer)id);
    if(LazyLoader.getInstance().containsKey(id)) {
        Object bitmap = LazyLoader.getInstance().getBitMap(id);
        if(null != bitmap && (bitmap instanceof  Bitmap)) {
            holder.getThumbView().setImageBitmap((Bitmap)bitmap);
        } else {
            holder.getThumbView().setImageDrawable(null);
        }
    } else {
        holder.getThumbView().setImageDrawable(null);
        LazyItem lazyItem = new LazyItem();
        lazyItem.setId(id);
        lazyItem.setThumbNail(holder.getThumbView());
        LazyLoader.getInstance().putItem(lazyItem);
    }
}




public class LazyLoaderHelper extends Thread {

    private ContentResolver resolver = null;
    private Activity activity;
    private boolean isActive = true;
    ExecutorService executor;


    public LazyLoaderHelper(Activity _activity , ContentResolver _resolver) {
        resolver = _resolver;
        activity = _activity;
        isActive = true;
        executor = Executors.newFixedThreadPool(10);
    }

    public void stopThread() {
        isActive = false;
        executor.shutdown();
    }

    @Override
    public void run() {
        while (isActive) {
            if(LazyLoader.getInstance().getSize() > 0) {
                final  LazyItem lazyItem = LazyLoader.getInstance().getItem();
                if(null != lazyItem) {

                    executor.execute(new Runnable() {
                        @Override
                        public void run() {

                            BitmapFactory.Options options = new BitmapFactory.Options();
                            options.inSampleSize = 1;

                            if ((null != resolver) && (null != activity)) {
                                final Bitmap thumb = MediaStore.Video.Thumbnails.getThumbnail(resolver, lazyItem.getId(), MediaStore.Video.Thumbnails.MICRO_KIND, options);
                                if (null != thumb) {
                                    LazyLoader.getInstance().putBitMap(lazyItem.getId(), thumb);
                                } else {
                                    LazyLoader.getInstance().putBitMap(lazyItem.getId(), new Object());
                                }

                                if ((Integer) lazyItem.getThumbNail().getTag() == lazyItem.getId()) {
                                    activity.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            if (null != thumb) {
                                                lazyItem.getThumbNail().setImageBitmap(thumb);
                                            } else {
                                                lazyItem.getThumbNail().setImageDrawable(null);
                                            }
                                        }
                                    });
                                }
                            }
                        }
                    });
                }
            }

        }
    }
}

【问题讨论】:

  • 图片延迟加载我推荐UIL
  • 发布您的适配器代码
  • 你使用 ViewBinder 吗?如果是这样,也发布它的代码

标签: android


【解决方案1】:

您可以使用适用于 android 的 picaso 库,它是开源的,可以轻松集成到您的应用程序中,您可以从下面的链接从 github 下载该库

http://square.github.io/picasso/

并且可以通过在列表视图适配器中使用以下方法轻松实现延迟加载

Picasso 支持下载和错误占位符作为可选功能。

毕加索.with(上下文) .load(网址) .placeholder(R.drawable.user_placeholder) .error(R.drawable.user_placeholder_error) .into(imageView);

资源、资产、文件、内容提供者都支持作为图像源。

Picasso.with(context).load(R.drawable.landing_screen).into(imageView1); Picasso.with(context).load("file:///android_asset/DvpvklR.png").into(imageView2); Picasso.with(context).load(new File(...)).into(imageView3);

【讨论】:

    【解决方案2】:

    各种库可用于延迟加载图像。 Picasso & Glide 非常好。集成也很容易。 如果图像质量最重要,您可以使用 Picasso。 使用滑行更快加载。 虽然你可以喜欢任何人,但我建议使用 Glide。

    对于交换的图像,图像的异步加载可能存在问题。 你怎么知道线程完成。任何线程都可以随时加载图片。

    谢谢

    【讨论】:

      【解决方案3】:
      • 我正在使用aQuery 库来延迟加载位图(它也支持http)。无需进行大量更改即可与现有代码集成非常简单易行。
      • 使项目的布局尽可能简单。
      • 确保正确实施回收和 View Holder 模式。

      更多关于平滑列表滚动的信息是here

      【讨论】:

        【解决方案4】:

        在我看来,你应该试试UIL (Universal Image Loader) 该库可以显示视频缩略图以及图像缩略图。

        编辑: 将imageLoader.displayImage(String uri, ImageView imgView, DisplayImageOptions options); 添加到您的getView 或您的custom adapter

        String uri 可以是file:///mnt/sdcard/video.mp4 // 来自 SD 卡(视频缩略图)

        希望对您有所帮助!如果您有任何问题,请在下方评论

        【讨论】:

        • 这并没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方发表评论 - 您可以随时评论自己的帖子,一旦您有足够的reputation,您就可以comment on any post
        • 我明白了。谢谢,加布里埃尔
        • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
        • @Gosu,我根据你的建议修改了答案。谢谢
        【解决方案5】:

        我建议您将 ViewHolder 模式与名为 Picasso 的库结合使用。

        加载图片时,毕加索的样子:

        public static class ViewHolder {
            ...
            public ImageView imageView;
        }
        
        @Override
            public void bindView(View view, Context context, Cursor cursor) {
            ...
            String thumbnailURL = "image_url_from_cursor";
            Picasso.with(context).load(thumbnailURL)
                                            .placeholder(R.drawable.ic_default_img)
                                            .error(R.drawable.ic_default_img)
                                            .into(holder.imageView);
            ...
        

        希望对你有帮助。

        【讨论】:

          【解决方案6】:

          使用延迟加载很好,但我仍然更喜欢 Picasso android 库,它会自动设置缓存要求,并且图像加载所需的时间也会更少。我正在使用寻呼机适配器来查看寻呼机动画,这里我需要数量用于不同页面的图像。这是一个例子。

           public Object instantiateItem(ViewGroup container, int position) {
                   final ViewGroup cnt=container;
          
          
                       final int val=position;
          
          
                       View itemView = mLayoutInflater.inflate(R.layout.smallnewsview, container, false);
          
                      try
                      {
          
                       ImageView img=(ImageView)itemView.findViewById(R.id.imageView1);
          
                       Picasso.with(context)
                         .load("just image url....")
                         .into(img, new Callback() {
          
                    @Override
                    public void onSuccess() {
                      pbh.setVisibility(View.GONE);
                    }
          
                    @Override
                    public void onError() {
                        pbh.setVisibility(View.VISIBLE);
                    }
                  });
          

          现在下次它会自动调用缓存而不是每次都从服务器调用。我真的很喜欢这个图书馆。

          在这里你也可以得到图书馆。

          http://square.github.io/picasso/

          我希望这对您的支持非常有帮助。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-08-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-10-07
            • 1970-01-01
            相关资源
            最近更新 更多