java - 为什么 android ImageAdapter 不延迟加载图像?

标签 java android list listview android-asynctask

我有这个用于 android 的 listView 的 ImageAdapter:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View view = null;
    RelativeLayout relativeLayout = null;
    Offer currentOffer = mOffersList.get(position);

    if (convertView == null) { // create a new view if no recycling
                                // available
        // Make up a new view
        LayoutInflater inflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.offer_list_item, null);
        relativeLayout = (RelativeLayout) view
                .findViewById(R.id.offerImage);

    } else {
        view = (View) convertView;
        relativeLayout = (RelativeLayout) view
                .findViewById(R.id.offerImage);
        setBackgroundDrawable(relativeLayout, null);

    }

    String imageUrl = "";
    imageUrl = currentOffer.getImageUrl().toString();

    Bitmap bitmap = imageCache.get(imageUrl);

    if (bitmap != null) {
        Drawable dr = new BitmapDrawable(mContext.getResources(), bitmap);
        setBackgroundDrawable(relativeLayout, dr);
    } else {
        if (!downloadingImageUrls.contains(imageUrl)) {
            downloadingImageUrls.add(imageUrl);
            new DownloadImageAsyncTask().execute(imageUrl);
        }
    }

    return view;
}

还有这个:

class DownloadImageAsyncTask extends AsyncTask<String, Void, Void> {
        @Override
        protected Void doInBackground(String... params) {
            String imageUrl = params[0];
            try {
                Bitmap bitmap = BitmapFactory
                        .decodeStream((InputStream) new URL(imageUrl)
                                .getContent());
                imageCache.put(imageUrl, bitmap);

            } catch (IOException e) {
                Log.e("DownloadImageAsyncTask", "Error reading bitmap" + e);
            }
            downloadingImageUrls.remove(imageUrl);
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            notifyDataSetChanged();
        }
    }

为什么所有列表项都加载在一起?它是异步的,但不是一一进行的。全部一起。

如何延迟加载?

为什么这段代码效率更高?

// better
public class DownloadImageAsyncTask2 extends
        AsyncTask<String, Void, Bitmap> {
    private final ImageView imageView;

    public DownloadImageAsyncTask2(ImageView imageView) {
        this.imageView = imageView;
    }

    @Override
    protected void onPreExecute() {
        Log.i("DownloadImageAsyncTask", "Starting image download task...");
    }

    @Override
    protected Bitmap doInBackground(String... params) {
        try {
            return BitmapFactory.decodeStream((InputStream) new URL(
                    params[0]).getContent());
        } catch (IOException e) {
            Log.e("DownloadImageAsyncTask", "Error reading bitmap" + e);
        }
        return null;
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if (bitmap != null) {
            imageView.setImageBitmap(bitmap);
        }
    }
}

最佳答案

为了回答您最初的问题,您编写的任何适配器都与它的名称完全相同;它是一个适配器。它允许您将数据转换为 AdapterView 中显示的 View 。强制所有 View “延迟加载”是没有意义的,而且坦率地说,出于某些原因不应该这样做。

  1. 也许您已经预取了所有图像并且不需要延迟加载。也许它们甚至只是来自资源,根本不需要以特殊方式处理。
  2. 它如何知道从哪里延迟加载图像(数据库、内存映射、文件、网络资源、其他 Android 服务等)?这就是您编写适配器时的工作。

您可能会认为 Adapter 子类拥有 loadLazily(Uri image, ImageView view) 函数会很好。如果是这样,为什么不自己子类 AbsAdapter 并添加它或向 AOSP 提交补丁。然而,我怀疑您是否会同意即使是这样的函数也应该包含在适配器中。尽管在 Android 中依靠系统进行数据管理是多么正常的事情,但以有效的方式管理数据确实是您的工作。

要回答有关您提出的两种延迟加载方法的其他问题,区别在于第一种方法会导致 AdapterView 重新加载其所有 View ,而在第二种方法中,您只是使要加载的 View 无效图片。

我实际上并不同意第二种方法总体上“更好”,因为每次您的配置发生更改或进程终止并且需要重新加载 View 时,您都需要通过网络或文件系统进行新的调用加载您的图像。如果像第一种方法一样缓存它们,那么您至少可以避免需要通过配置更改重新加载所有图像。如果您编写了一个在自己的进程中运行的单独的图像加载服务(我不建议这样做),您还可以避免第二种情况(您的 :default 进程被杀死)。

重点是,您负责加载图像,而不是 Android。如果您希望为您完成,请查看这些出色的图像加载或其他 Android 通用资源获取库:Local image caching solution for Android: Square Picasso vs Universal Image Loader 。我个人用过Universal-Image-Loader之前并承认它的作用如广告所示。但是,它会将您的所有图像缓存在外部存储上,这可能不适合您。

关于java - 为什么 android ImageAdapter 不延迟加载图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21812448/

相关文章:

java - 当在 eclipse android 真实设备上运行我的程序时,我在 LogCat 中收到许多错误,所有这些错误是什么以及如何修复它们?

Android - 如何在图形中心对齐点?

python - 获取Python列表的当前索引

c# - 如何从 List<T> 转换为 IList<T> 的子类型

java - 如何获取远程主solr服务器已删除但仍存在于本地solr服务器中的已删除文档

java - 执行jar文件时出错

java - java程序抛出异常后如何继续执行?

java - 如何使用 JavaFX CSS 删除带有嵌套标签的按钮的填充

android - 在 Android 中将 AAR 转换为 JAR

java - 是否可以使用来自多个文本文件的数据在 java 中创建列表