我正在使用ListView来显示与这些图像相关的一些图像和标题。我正在从互联网上获取图像。是否有一种方法可以延迟加载图像,以便在文本显示时,UI不会被阻止,图像在下载时显示?
图像总数不是固定的。
我正在使用ListView来显示与这些图像相关的一些图像和标题。我正在从互联网上获取图像。是否有一种方法可以延迟加载图像,以便在文本显示时,UI不会被阻止,图像在下载时显示?
图像总数不是固定的。
当前回答
我使用droidQuery。从URL加载图像有两种机制。第一个(速记)简单地是:
$.with(myView).image(url);
这可以很容易地添加到ArrayAdapter的getView(…)方法中。
longhand方法将提供更多的控制,并具有此处未讨论的选项(如缓存和回调),但可以在此处找到将输出大小指定为200px x 200px的基本实现:
$.ajax(new AjaxOptions().url(url)
.type("GET")
.dataType("image")
.imageWidth(200).imageHeight(200)
.success(new Function() {
@Override
public void invoke($ droidQuery, Object... params) {
myImageView.setImageBitmap((Bitmap) params[0]);
}
})
.error(new Function() {
@Override
public void invoke($ droidQuery, Object... params) {
AjaxError e = (AjaxError) params[0];
Log.e("$", "Error " + e.status + ": " + e.error);
}
})
);
其他回答
我遇到了这个问题,并实现了lruCache。我相信你需要API 12或更高版本,或者使用兼容的v4库。lurCache是快速内存,但它也有预算,所以如果你担心,你可以使用磁盘缓存。。。这都在缓存位图中描述。
现在我将提供我的实现,它是我从任何地方调用的单例,如下所示:
//Where the first is a string and the other is a imageview to load.
DownloadImageTask.getInstance().loadBitmap(avatarURL, iv_avatar);
以下是理想的代码,在检索web图像时,缓存并在适配器的getView中调用上述代码:
public class DownloadImageTask {
private LruCache<String, Bitmap> mMemoryCache;
/* Create a singleton class to call this from multiple classes */
private static DownloadImageTask instance = null;
public static DownloadImageTask getInstance() {
if (instance == null) {
instance = new DownloadImageTask();
}
return instance;
}
//Lock the constructor from public instances
private DownloadImageTask() {
// Get max available VM memory, exceeding this amount will throw an
// OutOfMemory exception. Stored in kilobytes as LruCache takes an
// int in its constructor.
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
// Use 1/8th of the available memory for this memory cache.
final int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
// The cache size will be measured in kilobytes rather than
// number of items.
return bitmap.getByteCount() / 1024;
}
};
}
public void loadBitmap(String avatarURL, ImageView imageView) {
final String imageKey = String.valueOf(avatarURL);
final Bitmap bitmap = getBitmapFromMemCache(imageKey);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
} else {
imageView.setImageResource(R.drawable.ic_launcher);
new DownloadImageTaskViaWeb(imageView).execute(avatarURL);
}
}
private void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null) {
mMemoryCache.put(key, bitmap);
}
}
private Bitmap getBitmapFromMemCache(String key) {
return mMemoryCache.get(key);
}
/* A background process that opens a http stream and decodes a web image. */
class DownloadImageTaskViaWeb extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTaskViaWeb(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon = BitmapFactory.decodeStream(in);
}
catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
addBitmapToMemoryCache(String.valueOf(urldisplay), mIcon);
return mIcon;
}
/* After decoding we update the view on the main UI. */
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
}
嗯,从互联网加载图像有很多解决方案。您也可以使用Android Query库。它将为您提供所有必需的活动。确保您想做什么,并阅读库wiki页面。并解决了图像加载限制。
这是我的代码:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row, null);
}
ImageView imageview = (ImageView) v.findViewById(R.id.icon);
AQuery aq = new AQuery(convertView);
String imageUrl = "http://www.vikispot.com/z/images/vikispot/android-w.png";
aq.id(imageview).progress(this).image(imageUrl, true, true, 0, 0, new BitmapAjaxCallback() {
@Override
public void callback(String url, ImageView iv, Bitmap bm, AjaxStatus status) {
iv.setImageBitmap(bm);
}
));
return v;
}
它应该可以解决您的延迟加载问题。
Gilles Debonne的多线程性能教程。
这是来自Android开发者博客。建议的代码使用:
异步任务。一个硬的、有限大小的FIFO缓存。一个软的、易于垃圾收集的缓存。下载时可绘制的占位符。
我用图像制作了一个懒惰列表(位于GitHub)的简单演示。
基本用途ImageLoader ImageLoader=新的ImageLoader(上下文)。。。imageLoader.DisplayImage(url,imageView);不要忘记添加对AndroidManifest.xml的以下权限:<uses permission android:name=“android.ppermission.INTERNET”/><uses permission android:name=“android.permission.WRITE_EXTERNAL_STORAGE”/>请只创建ImageLoader的一个实例,并在您的应用这样,图像缓存将更加高效。
这可能对某人有帮助。它在后台线程中下载图像。图像缓存在SD卡和内存中。缓存的实现非常简单,对于演示来说就足够了。我使用inSampleSize解码图像以减少内存消耗。我还尝试正确处理回收的视图。
我只想再添加一个很好的示例,XML适配器。由于它被谷歌使用,我也在使用相同的逻辑来避免OutOfMemory错误。
基本上,这个ImageDownloader就是你的答案(因为它涵盖了你的大部分需求)。有些也可以在其中实现。