我有这个用于 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 “延迟加载”是没有意义的,而且坦率地说,出于某些原因不应该这样做。
- 也许您已经预取了所有图像并且不需要延迟加载。也许它们甚至只是来自资源,根本不需要以特殊方式处理。
- 它如何知道从哪里延迟加载图像(数据库、内存映射、文件、网络资源、其他 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/