延迟加载ListView中的图像

android image listview url universal-image-loader

535395 观看

30回复

40055 作者的声誉

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

图像总数不固定。

作者: lostInTransit 的来源 发布者: 2009 年 2 月 12 日

回应 30


40

2433 作者的声誉

The way I do it is by launching a thread to download the images in the background and hand it a callback for each list item. When an image is finished downloading it calls the callback which updates the view for the list item.

This method doesn't work very well when you're recycling views however.

作者: jasonhudgins 发布者: 2009 年 2 月 12 日

1067

13080 作者的声誉

决定

这是我创建的用于保存应用程序当前正在显示的图像的内容。请注意,这里使用的“ Log”对象是我在Android内部最终Log类周围的自定义包装。

package com.wilson.android.library;

/*
 Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/
import java.io.IOException;

public class DrawableManager {
    private final Map<String, Drawable> drawableMap;

    public DrawableManager() {
        drawableMap = new HashMap<String, Drawable>();
    }

    public Drawable fetchDrawable(String urlString) {
        if (drawableMap.containsKey(urlString)) {
            return drawableMap.get(urlString);
        }

        Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
        try {
            InputStream is = fetch(urlString);
            Drawable drawable = Drawable.createFromStream(is, "src");


            if (drawable != null) {
                drawableMap.put(urlString, drawable);
                Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
                        + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
                        + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
            } else {
              Log.w(this.getClass().getSimpleName(), "could not get thumbnail");
            }

            return drawable;
        } catch (MalformedURLException e) {
            Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
            return null;
        } catch (IOException e) {
            Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
            return null;
        }
    }

    public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
        if (drawableMap.containsKey(urlString)) {
            imageView.setImageDrawable(drawableMap.get(urlString));
        }

        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message message) {
                imageView.setImageDrawable((Drawable) message.obj);
            }
        };

        Thread thread = new Thread() {
            @Override
            public void run() {
                //TODO : set imageView to a "pending" image
                Drawable drawable = fetchDrawable(urlString);
                Message message = handler.obtainMessage(1, drawable);
                handler.sendMessage(message);
            }
        };
        thread.start();
    }

    private InputStream fetch(String urlString) throws MalformedURLException, IOException {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpGet request = new HttpGet(urlString);
        HttpResponse response = httpClient.execute(request);
        return response.getEntity().getContent();
    }
}
作者: James A Wilson 发布者: 2009 年 2 月 18 日

106

7593 作者的声誉

更新:请注意,此答案现在无效。垃圾收集器对SoftReference和WeakReference采取积极措施,因此此代码不适用于新应用。 (相反,请尝试其他答案中建议的库,例如Universal Image Loader。)

感谢James的代码,以及Bao-Long提出的使用SoftReference的建议。我在James的代码上实现了SoftReference更改。不幸的是,SoftReferences导致我的图像被垃圾收集的速度过快。就我而言,没有SoftReference的东西就很好了,因为我的列表大小有限并且图像很小。

一年前,有一个关于Google组上的SoftReferences的讨论:链接到thread。作为对过早的垃圾回收的解决方案,他们建议使用dalvik.system.VMRuntime.setMinimumHeapSize()手动设置VM堆大小的可能性,这对我来说不是很有吸引力。

public DrawableManager() {
    drawableMap = new HashMap<String, SoftReference<Drawable>>();
}

public Drawable fetchDrawable(String urlString) {
    SoftReference<Drawable> drawableRef = drawableMap.get(urlString);
    if (drawableRef != null) {
        Drawable drawable = drawableRef.get();
        if (drawable != null)
            return drawable;
        // Reference has expired so remove the key from drawableMap
        drawableMap.remove(urlString);
    }

    if (Constants.LOGGING) Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
    try {
        InputStream is = fetch(urlString);
        Drawable drawable = Drawable.createFromStream(is, "src");
        drawableRef = new SoftReference<Drawable>(drawable);
        drawableMap.put(urlString, drawableRef);
        if (Constants.LOGGING) Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
                + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
                + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
        return drawableRef.get();
    } catch (MalformedURLException e) {
        if (Constants.LOGGING) Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
        return null;
    } catch (IOException e) {
        if (Constants.LOGGING) Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
        return null;
    }
}

public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
    SoftReference<Drawable> drawableRef = drawableMap.get(urlString);
    if (drawableRef != null) {
        Drawable drawable = drawableRef.get();
        if (drawable != null) {
            imageView.setImageDrawable(drawableRef.get());
            return;
        }
        // Reference has expired so remove the key from drawableMap
        drawableMap.remove(urlString);
    }

    final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            imageView.setImageDrawable((Drawable) message.obj);
        }
    };

    Thread thread = new Thread() {
        @Override
        public void run() {
            //TODO : set imageView to a "pending" image
            Drawable drawable = fetchDrawable(urlString);
            Message message = handler.obtainMessage(1, drawable);
            handler.sendMessage(message);
        }
    };
    thread.start();
}
作者: TalkLittle 发布者: 2010 年 5 月 5 日

1017

41061 作者的声誉

我做了一个带有图像的惰性列表的简单演示(位于GitHub上)。

基本用法

ImageLoader imageLoader=new ImageLoader(context); ...
imageLoader.DisplayImage(url, imageView); 

不要忘记向您的AndroidManifest.xml添加以下权限:

 <uses-permission android:name="android.permission.INTERNET"/>
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> Please

仅创建一个ImageLoader实例,并在您的应用程序中重复使用它。这样,图像缓存将更加高效。

这可能对某人有帮助。它将在后台线程中下载图像。图像被缓存在SD卡和内存中。缓存的实现非常简单,足以用于演示。我使用inSampleSize解码图像以减少内存消耗。我也尝试正确处理回收的视图。

替代文字

作者: Fedor 发布者: 2010 年 6 月 18 日

155

22786 作者的声誉

Gilles Debunne撰写的教程Multi Performanceing for Performance

这是来自Android开发者博客。建议的代码使用:

  • AsyncTasks
  • 硬而有限的尺寸FIFO cache
  • 一个易于编辑的软garbage collect缓存。
  • 下载时的占位符 Drawable

在此处输入图片说明

作者: Thomas Ahle 发布者: 2010 年 8 月 12 日

51

3167 作者的声誉

I've written a tutorial that explains how to do lazy-loading of images in a listview. I go into some detail about the issues of recycling and concurrency. I also use a fixed thread pool to prevent spawning a lot of threads.

Lazy loading of images in Listview Tutorial

作者: Ben Ruijl 发布者: 2011 年 8 月 27 日

81

11249 作者的声誉

高性能加载程序-在检查了此处建议的方法后,我使用了Ben的解决方案并进行了一些更改-

  1. 我意识到使用可绘制对象比使用位图更快,因此我改用可绘制对象

  2. Using SoftReference is great, but it makes the cached image to be deleted too often, so I added a Linked list that holds images references, preventing from the image to be deleted, until it reached a predefined size

  3. To open the InputStream I used java.net.URLConnection which allows me to use web cache (you need to set a response cache first, but that's another story)

My code:

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;
}
}
作者: Asaf Pinhassi 发布者: 2011 年 10 月 22 日

31

16276 作者的声誉

I just want to add one more good example, XML Adapters. As it's is used by Google and I am also using the same logic to avoid an OutOfMemory error.

Basically this ImageDownloader is your answer (as it covers most of your requirements). Some you can also implement in that.

作者: Arslan Anwar 发布者: 2011 年 12 月 14 日

548

12176 作者的声誉

我建议使用开放源代码工具Universal Image Loader。它最初是基于Fedor Vlasov的项目LazyList进行的,此后得到了极大的改进。

  • 多线程图像加载
  • 可以广泛调整ImageLoader的配置(线程执行程序,下载器,解码器,内存和磁盘缓存,显示图像选项等)
  • 内存和/或设备文件系统(或SD卡)中图像缓存的可能性
  • “监听”加载过程的可能性
  • 可以使用单独的选项自定义每个显示图像调用
  • 小部件支持
  • Android 2.0+支持

作者: nostra13 发布者: 2011 年 12 月 19 日

20

2612 作者的声誉

Have a look at Shutterbug, Applidium's lightweight SDWebImage (a nice library on iOS) port to Android. It supports asynchronous caching, stores failed URLs, handles concurrency well, and helpful subclasses are included.

Pull requests (and bug reports) are welcome, too!

作者: PatrickNLT 发布者: 2012 年 10 月 16 日

24

496 作者的声誉

I think this issue is very popular among Android developers, and there are plenty of such libraries that claims to resolve this issue, but only a few of them seems to be on the mark. AQuery is one such library, but it is better than most of them in all aspects and is worth trying for.

作者: Ritesh Kumar Dubey 发布者: 2012 年 12 月 11 日

77

4438 作者的声誉

I have followed this Android Training and I think it does an excellent job at downloading images without blocking the main UI. It also handles caching and dealing with scrolling through many images: Loading Large Bitmaps Efficiently

作者: toobsco42 发布者: 2012 年 12 月 27 日

15

4379 作者的声誉

Novoda also has a great lazy image loading library and many apps like Songkick, Podio, SecretDJ and ImageSearch use their library.

Their library is hosted here on Github and they have a pretty active issues tracker as well. Their project seems to be pretty active too, with over 300+ commits at the time of writing this reply.

作者: Soham 发布者: 2013 年 1 月 12 日

25

539 作者的声誉

Well, image loading time from the Internet has many solutions. You may also use the library Android-Query. It will give you all the required activity. Make sure what you want to do and read the library wiki page. And solve the image loading restriction.

This is my code:

@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;
}

It should be solve your lazy loading problem.

作者: Rahul Rawat 发布者: 2013 年 2 月 12 日

13

1292 作者的声誉

Check my fork of LazyList. Basically, I improve the LazyList by delaying the call of the ImageView and create two methods:

  1. When you need to put something like "Loading image..."
  2. When you need to show the downloaded image.

I also improved the ImageLoader by implementing a singleton in this object.

作者: Nicolas Jafelle 发布者: 2013 年 2 月 12 日

16

43819 作者的声誉

DroidParts has ImageFetcher that requires zero configuration to get started.

  • Uses a disk & in-memory Least Recently Used (LRU) cache.
  • Efficiently decodes images.
  • Supports modifying bitmaps in background thread.
  • Has simple cross-fade.
  • Has image loading progress callback.

Clone DroidPartsGram for an example:

在此处输入图片说明

作者: yanchenko 发布者: 2013 年 5 月 6 日

28

505 作者的声誉

I have been using NetworkImageView from the new Android Volley Library com.android.volley.toolbox.NetworkImageView, and it seems to be working pretty well. Apparently, this is the same view that is used in Google Play and other new Google applications. Definitely worth checking out.

作者: droidment 发布者: 2013 年 6 月 13 日

4

51 作者的声誉

public class ImageDownloader {

Map<String, Bitmap> imageCache;

public ImageDownloader() {
    imageCache = new HashMap<String, Bitmap>();

}

// download function
public void download(String url, ImageView imageView) {
    if (cancelPotentialDownload(url, imageView)) {

        // Caching code right here
        String filename = String.valueOf(url.hashCode());
        File f = new File(getCacheDirectory(imageView.getContext()),
                filename);

        // Is the bitmap in our memory cache?
        Bitmap bitmap = null;

        bitmap = (Bitmap) imageCache.get(f.getPath());

        if (bitmap == null) {

            bitmap = BitmapFactory.decodeFile(f.getPath());

            if (bitmap != null) {
                imageCache.put(f.getPath(), bitmap);
            }

        }
        // No? download it
        if (bitmap == null) {
            try {
                BitmapDownloaderTask task = new BitmapDownloaderTask(
                        imageView);
                DownloadedDrawable downloadedDrawable = new DownloadedDrawable(
                        task);
                imageView.setImageDrawable(downloadedDrawable);
                task.execute(url);
            } catch (Exception e) {
                Log.e("Error==>", e.toString());
            }

        } else {
            // Yes? set the image
            imageView.setImageBitmap(bitmap);
        }
    }
}

// cancel a download (internal only)
private static boolean cancelPotentialDownload(String url,
        ImageView imageView) {
    BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

    if (bitmapDownloaderTask != null) {
        String bitmapUrl = bitmapDownloaderTask.url;
        if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
            bitmapDownloaderTask.cancel(true);
        } else {
            // The same URL is already being downloaded.
            return false;
        }
    }
    return true;
}

// gets an existing download if one exists for the imageview
private static BitmapDownloaderTask getBitmapDownloaderTask(
        ImageView imageView) {
    if (imageView != null) {
        Drawable drawable = imageView.getDrawable();
        if (drawable instanceof DownloadedDrawable) {
            DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable;
            return downloadedDrawable.getBitmapDownloaderTask();
        }
    }
    return null;
}

// our caching functions
// Find the dir to save cached images
private static File getCacheDirectory(Context context) {
    String sdState = android.os.Environment.getExternalStorageState();
    File cacheDir;

    if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
        File sdDir = android.os.Environment.getExternalStorageDirectory();

        // TODO : Change your diretcory here
        cacheDir = new File(sdDir, "data/ToDo/images");
    } else
        cacheDir = context.getCacheDir();

    if (!cacheDir.exists())
        cacheDir.mkdirs();
    return cacheDir;
}

private void writeFile(Bitmap bmp, File f) {
    FileOutputStream out = null;

    try {
        out = new FileOutputStream(f);
        bmp.compress(Bitmap.CompressFormat.PNG, 80, out);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (out != null)
                out.close();
        } catch (Exception ex) {
        }
    }
}

// download asynctask
public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
    private String url;
    private final WeakReference<ImageView> imageViewReference;

    public BitmapDownloaderTask(ImageView imageView) {
        imageViewReference = new WeakReference<ImageView>(imageView);
    }

    @Override
    // Actual download method, run in the task thread
    protected Bitmap doInBackground(String... params) {
        // params comes from the execute() call: params[0] is the url.
        url = (String) params[0];
        return downloadBitmap(params[0]);
    }

    @Override
    // Once the image is downloaded, associates it to the imageView
    protected void onPostExecute(Bitmap bitmap) {
        if (isCancelled()) {
            bitmap = null;
        }

        if (imageViewReference != null) {
            ImageView imageView = imageViewReference.get();
            BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
            // Change bitmap only if this process is still associated with
            // it
            if (this == bitmapDownloaderTask) {
                imageView.setImageBitmap(bitmap);

                // cache the image

                String filename = String.valueOf(url.hashCode());
                File f = new File(
                        getCacheDirectory(imageView.getContext()), filename);

                imageCache.put(f.getPath(), bitmap);

                writeFile(bitmap, f);
            }
        }
    }

}

static class DownloadedDrawable extends ColorDrawable {
    private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;

    public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
        super(Color.WHITE);
        bitmapDownloaderTaskReference = new WeakReference<BitmapDownloaderTask>(
                bitmapDownloaderTask);
    }

    public BitmapDownloaderTask getBitmapDownloaderTask() {
        return bitmapDownloaderTaskReference.get();
    }
}

// the actual download code
static Bitmap downloadBitmap(String url) {
    HttpParams params = new BasicHttpParams();
    params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
            HttpVersion.HTTP_1_1);
    HttpClient client = new DefaultHttpClient(params);
    final HttpGet getRequest = new HttpGet(url);

    try {
        HttpResponse response = client.execute(getRequest);
        final int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != HttpStatus.SC_OK) {
            Log.w("ImageDownloader", "Error " + statusCode
                    + " while retrieving bitmap from " + url);
            return null;
        }

        final HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream inputStream = null;
            try {
                inputStream = entity.getContent();
                final Bitmap bitmap = BitmapFactory
                        .decodeStream(inputStream);
                return bitmap;
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                entity.consumeContent();
            }
        }
    } catch (Exception e) {
        // Could provide a more explicit error message for IOException or
        // IllegalStateException
        getRequest.abort();
        Log.w("ImageDownloader", "Error while retrieving bitmap from "
                + url + e.toString());
    } finally {
        if (client != null) {
            // client.close();
        }
    }
    return null;
 }
}
作者: Nikhil Gupta 发布者: 2013 年 7 月 18 日

4

29031 作者的声誉

我遇到了这个问题,并实现了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);
        }
    }
}
作者: j2emanue 发布者: 2013 年 7 月 21 日

7

6147 作者的声誉

我可以推荐一种像魅力一样工作的方法:Android查询。

您可以从此处下载该JAR文件

AQuery androidAQuery = new AQuery(this);

举个例子:

androidAQuery.id(YOUR IMAGEVIEW).image(YOUR IMAGE TO LOAD, true, true, getDeviceWidth(), ANY DEFAULT IMAGE YOU WANT TO SHOW);

它非常快速且准确,使用它您可以找到许多其他功能,例如加载时的动画,获取位图(如果需要)等。

作者: Pratik Dasa 发布者: 2013 年 7 月 29 日

28

7829 作者的声誉

This is a common problem on Android that has been solved in many ways by many people. In my opinion the best solution I've seen is the relatively new library called Picasso. Here are the highlights:

  • Open source, but headed up by Jake Wharton of ActionBarSherlock fame.
  • Asynchronously load images from network or app resources with one line of code
  • Automatic ListView detection
  • Automatic disk and memory caching
  • Can do custom transformations
  • Lots of configurable options
  • Super simple API
  • Frequently updated
作者: howettl 发布者: 2013 年 10 月 15 日

7

687 作者的声誉

Aquery一试。它具有惊人的简单方法来异步加载和缓存图像。

作者: user2779311 发布者: 2013 年 12 月 16 日

7

91 作者的声誉

URLImageViewHelper是一个了不起的库,可以帮助您做到这一点。

作者: DiegoAlt 发布者: 2014 年 1 月 27 日

94

2728 作者的声誉

毕加索

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

适用于Android的功能强大的图像下载和缓存库。

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

Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

毕加索会自动处理Android上许多常见的图片加载陷阱:

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

毕加索·杰克·沃顿的图书馆

滑行

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

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

Glide.with(this).load("http://goo.gl/h8qOq7").into(imageView);

Glide的主要重点是使任何种类的图像列表尽可能平滑和快速地滚动,但是Glide在几乎所有需要获取,调整大小和显示远程图像的情况下也有效。

滑行图像加载库

Facebook的壁画

Fresco是一个功能强大的系统,可在Android应用程序中显示图像。

壁画负责图像的加载和显示,因此您不必这样做。它将从网络,本地存储或本地资源中加载图像,并显示一个占位符,直到图像到达为止。它具有两个级别的缓存;一个在内存中,另一个在内部存储器中。

壁画Github

在Android 4.x及更低版本中,Fresco将图像放置在Android内存的特殊区域中。这使您的应用程序运行得更快-并减少了发生可怕的OutOfMemoryError的频率。

壁画文档

作者: Ashwin S Ashok 发布者: 2014 年 4 月 4 日

63

2821 作者的声誉

1. Picasso allows for hassle-free image loading in your application—often in one line of code!

Use Gradle:

implementation 'com.squareup.picasso:picasso:2.71828'

Just one line of code!

Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(imageView);

2. Glide An image loading and caching library for Android focused on smooth scrolling

Use Gradle:

repositories {
  mavenCentral() 
  google()
}

dependencies {
   implementation 'com.github.bumptech.glide:glide:4.7.1'
   annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
}

// For a simple view:

  Glide.with(this).load("http://i.imgur.com/DvpvklR.png").into(imageView);

3. fresco is a powerful system for displaying images in Android applications.Fresco takes care of image loading and display, so you don't have to.

Getting Started with Fresco

作者: chiragkyada 发布者: 2014 年 5 月 22 日

16

460 作者的声誉

Just a quick tip for someone who is in indecision regarding what library to use for lazy-loading images:

There are four basic ways.

  1. DIY => Not the best solution but for a few images and if you want to go without the hassle of using others libraries

  2. Volley's Lazy Loading library => From guys at android. It is nice and everything but is poorly documented and hence is a problem to use.

  3. Picasso: A simple solution that just works, you can even specify the exact image size you want to bring in. It is very simple to use but might not be very "performant" for apps that has to deal with humongous amounts of images.

  4. UIL: The best way to lazy load images. You can cache images(you need permission of course), initialize the loader once, then have your work done. The most mature asynchronous image loading library I have ever seen so far.

作者: Bijay Koirala 发布者: 2014 年 8 月 3 日

21

762 作者的声誉

You must try this Universal Loader is best. I am using this after done many RnD on lazy loading .

Universal Image Loader

Features

  • Multithread image loading (async or sync)
  • Wide customization of ImageLoader's configuration (thread executors, downloader, decoder, memory and disk cache, display image options, etc.)
  • Many customization options for every display image call (stub images, caching switch, decoding options, Bitmap processing and displaying, etc.)
  • Image caching in memory and/or on disk (device's file system or SD card)
  • Listening loading process (including downloading progress)

Android 2.0+ support

在此处输入图片说明

作者: Girish Patel 发布者: 2015 年 2 月 5 日

11

478 作者的声誉

以上所有代码都有自己的价值,但以我的个人经验,请尝试使用毕加索。

毕加索 是一个专门用于此目的的库,实际上它会自动管理缓存和所有其他网络操作。您将不得不在项目中添加库,只需编写一行代码即可从远程URL加载图像。

请访问此处:http : //code.tutsplus.com/tutorials/android-sdk-working-with-picasso--cms-22149

作者: AKber 发布者: 2015 年 7 月 9 日

9

356 作者的声誉

使用滑行库。它适用于我,也适用于您的代码,适用于图像和gif。

ImageView imageView = (ImageView) findViewById(R.id.test_image); 
    GlideDrawableImageViewTarget imagePreview = new GlideDrawableImageViewTarget(imageView);
    Glide
            .with(this)
            .load(url)
            .listener(new RequestListener<String, GlideDrawable>() {
                @Override
                public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {                       
                    return false;
                }

                @Override
                public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                    return false;
                }
            })
            .into(imagePreview);
}
作者: Saket Kumar 发布者: 2017 年 3 月 16 日

12

623 作者的声誉

如果要显示Facebook的Shimmer布局,则有一个官方的Facebook库。FaceBook微光Android

它会处理所有事情,您只需要以嵌套的方式将所需的设计代码放在微光框架中即可。这是示例代码。

<com.facebook.shimmer.ShimmerFrameLayout
     android:id=“@+id/shimmer_view_container”
     android:layout_width=“wrap_content”
     android:layout_height="wrap_content"
     shimmer:duration="1000">

 <here will be your content to display />

</com.facebook.shimmer.ShimmerFrameLayout>

这是它的Java代码。

ShimmerFrameLayout shimmerContainer = (ShimmerFrameLayout) findViewById(R.id.shimmer_view_container);
shimmerContainer.startShimmerAnimation();

在您的gradle文件中添加此依赖项。

implementation 'com.facebook.shimmer:shimmer:0.1.0@aar'

这是它的样子。闪光Android屏幕截图

作者: Zankrut Parmar 发布者: 2018 年 2 月 26 日
32x32