我正在使用ListView来显示与这些图像相关的一些图像和标题。我正在从互联网上获取图像。是否有一种方法可以延迟加载图像,以便在文本显示时,UI不会被阻止,图像在下载时显示?

图像总数不是固定的。


当前回答

DroidParts的ImageFetcher需要零配置才能启动。

使用磁盘和内存中最近最少使用(LRU)缓存。高效解码图像。支持在后台线程中修改位图。具有简单的交叉褪色。具有图像加载进度回调。

例如,克隆DroidPartsGram:

其他回答

Novoda还有一个很棒的懒人图像加载库,许多应用程序如Songkick、Podio、SecretDJ和ImageSearch都使用其库。

他们的库托管在Github上,他们还有一个非常活跃的问题跟踪程序。他们的项目似乎也很活跃,在撰写回复时提交了超过300次。

对于那些对使用什么库来延迟加载图像犹豫不决的人来说,这只是一个快速提示:

有四种基本方法。

DIY=>不是最好的解决方案,但对于一些图像,如果你想不使用其他库的麻烦Volley的懒加载库=>来自android的家伙。它很好,一切都很好,但文档记录很差,因此使用起来有问题。毕加索:一个简单可行的解决方案,你甚至可以指定你想要引入的图像大小。它非常简单,但对于需要处理大量图像的应用程序来说,可能不是很“高效”。UIL:延迟加载图像的最佳方式。您可以缓存图像(当然需要权限),初始化加载程序一次,然后完成工作。迄今为止,我见过最成熟的异步图像加载库。

高性能加载器-在检查了这里建议的方法之后,我用了Ben的解决方案-

我意识到使用drawable比使用位图更快,所以我使用了drawable使用SoftReference很好,但它会使缓存的图像太频繁地被删除,所以我添加了一个保存图像引用的链接列表,防止图像被删除,直到达到预定义的大小为了打开InputStream,我使用java.net.URLConnection,它允许我使用web缓存(您需要先设置响应缓存,但这是另一回事)

我的代码:

import java.util.Map; 
import java.util.HashMap; 
import java.util.LinkedList; 
import java.util.Collections; 
import java.util.WeakHashMap; 
import java.lang.ref.SoftReference; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ExecutorService; 
import android.graphics.drawable.Drawable;
import android.widget.ImageView;
import android.os.Handler;
import android.os.Message;
import java.io.InputStream;
import java.net.MalformedURLException; 
import java.io.IOException; 
import java.net.URL;
import java.net.URLConnection;

public class DrawableBackgroundDownloader {    

private final Map<String, SoftReference<Drawable>> mCache = new HashMap<String, SoftReference<Drawable>>();   
private final LinkedList <Drawable> mChacheController = new LinkedList <Drawable> ();
private ExecutorService mThreadPool;  
private final Map<ImageView, String> mImageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());  

public static int MAX_CACHE_SIZE = 80; 
public int THREAD_POOL_SIZE = 3;

/**
 * Constructor
 */
public DrawableBackgroundDownloader() {  
    mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);  
}  


/**
 * Clears all instance data and stops running threads
 */
public void Reset() {
    ExecutorService oldThreadPool = mThreadPool;
    mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
    oldThreadPool.shutdownNow();

    mChacheController.clear();
    mCache.clear();
    mImageViews.clear();
}  

public void loadDrawable(final String url, final ImageView imageView,Drawable placeholder) {  
    mImageViews.put(imageView, url);  
    Drawable drawable = getDrawableFromCache(url);  

    // check in UI thread, so no concurrency issues  
    if (drawable != null) {  
        //Log.d(null, "Item loaded from mCache: " + url);  
        imageView.setImageDrawable(drawable);  
    } else {  
        imageView.setImageDrawable(placeholder);  
        queueJob(url, imageView, placeholder);  
    }  
} 


private Drawable getDrawableFromCache(String url) {  
    if (mCache.containsKey(url)) {  
        return mCache.get(url).get();  
    }  

    return null;  
}

private synchronized void putDrawableInCache(String url,Drawable drawable) {  
    int chacheControllerSize = mChacheController.size();
    if (chacheControllerSize > MAX_CACHE_SIZE) 
        mChacheController.subList(0, MAX_CACHE_SIZE/2).clear();

    mChacheController.addLast(drawable);
    mCache.put(url, new SoftReference<Drawable>(drawable));

}  

private void queueJob(final String url, final ImageView imageView,final Drawable placeholder) {  
    /* Create handler in UI thread. */  
    final Handler handler = new Handler() {  
        @Override  
        public void handleMessage(Message msg) {  
            String tag = mImageViews.get(imageView);  
            if (tag != null && tag.equals(url)) {
                if (imageView.isShown())
                    if (msg.obj != null) {
                        imageView.setImageDrawable((Drawable) msg.obj);  
                    } else {  
                        imageView.setImageDrawable(placeholder);  
                        //Log.d(null, "fail " + url);  
                    } 
            }  
        }  
    };  

    mThreadPool.submit(new Runnable() {  
        @Override  
        public void run() {  
            final Drawable bmp = downloadDrawable(url);
            // if the view is not visible anymore, the image will be ready for next time in cache
            if (imageView.isShown())
            {
                Message message = Message.obtain();  
                message.obj = bmp;
                //Log.d(null, "Item downloaded: " + url);  

                handler.sendMessage(message);
            }
        }  
    });  
}  



private Drawable downloadDrawable(String url) {  
    try {  
        InputStream is = getInputStream(url);

        Drawable drawable = Drawable.createFromStream(is, url);
        putDrawableInCache(url,drawable);  
        return drawable;  

    } catch (MalformedURLException e) {  
        e.printStackTrace();  
    } catch (IOException e) {  
        e.printStackTrace();  
    }  

    return null;  
}  


private InputStream getInputStream(String urlString) throws MalformedURLException, IOException {
    URL url = new URL(urlString);
    URLConnection connection;
    connection = url.openConnection();
    connection.setUseCaches(true); 
    connection.connect();
    InputStream response = connection.getInputStream();

    return response;
}
}

滑行

Glide是一个快速高效的Android开源媒体管理框架,它将媒体解码、内存和磁盘缓存以及资源池打包成一个简单易用的界面。

Glide支持获取、解码和显示视频剧照、图像和动画GIF。Glide包含一个灵活的API,允许开发人员插入几乎任何网络堆栈。默认情况下,Glide使用一个基于HttpUrlConnection的自定义堆栈,但也包括Google的Volley项目或Square的OkHttp库的实用程序库插件。

Glide.with(this).load("your-url-here").into(imageView);

Glide的主要关注点是尽可能平滑快速地滚动任何类型的图像列表,但Glide对于任何需要获取、调整大小和显示远程图像的情况都非常有效。

Glide库

毕加索

使用杰克·沃顿的毕加索图书馆。(ActionBarSherlock开发人员提供的完美图像加载库)

一个强大的Android图像下载和缓存库。

图像为Android应用程序添加了急需的上下文和视觉效果。Picasso允许在应用程序中轻松加载图像,通常只需一行代码!

Picasso.with(context).load("your-url-here").into(imageView);

在Android上加载图像的许多常见陷阱都由毕加索自动处理:

在适配器中处理ImageView回收和下载取消。使用最少内存的复杂图像转换。自动内存和磁盘缓存。

毕加索图书馆

您可以使用一些第三方库(如Piccaso或Volley)进行有效的延迟加载。您还可以通过实现以下内容创建自己的

用于从url下载图像的实现代码实现用于存储和检索图像的缓存机制(使用android的LruCache进行缓存)