38 题: ListView中的图像延迟加载

在...创建的问题 Fri, Apr 28, 2017 12:00 AM

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

图像总数不固定。

    
1849
  1. 您可以使用 GreenDroid的AsyncImageView 。只需拨打setUrl
    2011-12-09 15:11:52Z
  2. 我用过它。这是一个很棒的实现。糟糕的消息是,AsyncImageView是大型GreenDroid项目的一部分,即使在您需要的所有情况下也可以使您的应用程序更大,这是AsyncImageView。此外,似乎,GreenDroid项目自2011年以来未更新。
    2012-04-15 11:06:07Z
  3. 你甚至可以尝试这个库: Android-http-image-manager 在我看来最适合异步加载图片。
    2012-11-09 11:43:54Z
  4. 只要使用Picasso,它就可以完成所有工作。 'Picasso.with(yourContext).load(img src /path /drawable here).into(imageView即你的目标);'多数民众赞成!
    2014-01-23 06:40:59Z
  5. 尝试使用: github。 com /nostra13 /Android-Universal-Image-Loader ,这个库非常快速有效地用于延迟加载和图像缓存
    2014-08-16 05:44:44Z
  6. 醇>
    30答案                              30 跨度>                         

    这是我创建的用于保存我的应用当前正在显示的图像的内容。请注意,这里使用的“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();
        }
    }
    
        
    1058
    2019-03-22 13:02:14Z
    1. 我认为你应该使用SoftReferences,这样你的程序永远不会导致OutOfMemoryException。由于GC可以在堆大小增加时清除软引用...您可以管理自己的生成,就像几秒钟后您可以将图像放到该列表中,在加载之前,您应检查是否存在图像然后再不下载而是收集它从该列表中并将其放回到您的softref列表中,之后您可以清除您的硬件列表:)
      2011-01-18 08:08:32Z
    2. Google Shelves项目是一个很好的例子,看看他们是如何做到的 code.google.com/p/shelves
      2011-01-18 08:09:41Z
    3. 当drawableMap包含图像时,你不会错过一个返回...没有启动提取线程吗?
      2011-03-29 22:06:40Z
    4. 此代码有几个问题。首先,你应该缓存Drawables,这将导致内存泄漏: stackoverflow.com /questions /7648740 /...... 。其次是缓存本身从来没有被清除所以它会永远增长,这是另一个内存泄漏。
      2011-11-15 05:35:45Z
    5. 2013-05-28 07:26:38Z
    6. 醇>

    我用图片制作了一个懒惰列表的简单演示(位于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解码图像以减少内存消耗。我也尝试正确处理回收的视图。

        
    1011
    2019-03-22 18:08:02Z
    1. 谢谢,我在我的项目中几乎无处不在使用稍微修改过的代码版本: code.google.com/p/vimeoid/source/browse/apk/src/com/fedorvlasov /...
      2010-10-12 18:18:02Z
    2. 有没有人看过Gilles Debunne的代码作为替代方案。我看到的两个巨大差异是1)在内存缓存与SD卡和2)使用AsyncTasks而不是线程池。 android-developers.blogspot.com/2010/07/...
      2010-10-29 20:39:35Z
    3. 有一个错误,有时会被解雇:10-13 09:58:46.738:ERROR /AndroidRuntime(24250):未捕获的处理程序:由于未捕获的异常导致主要退出10-13 09:58:46.768:ERROR /AndroidRuntime(24250):java.lang.ArrayIndexOutOfBoundsException:数组索引超出范围:0 10-13 09:58:46.768:ERROR /AndroidRuntime(24250):at java.util。 Vector.elementAt(Vector.java:331)10-13 09:58:46.768:ERROR /AndroidRuntime(24250):at java.util.Vector.get(Vector.java:445)10-13 09:58:46.768:错误/AndroidRuntime(24250):在com.my.app.image.ImageLoader $PhotosQueue.Clean(ImageLoader.java:91)
      2011-10-13 08:02:27Z
    4. 我想为像我这样的新手添加如果你想将这个代码添加到你自己的项目中,你必须在清单中添加外部缓存权限。谢谢
      2011-11-03 22:29:35Z
    5. @ BruceHill最新源代码中没有photosQueue。你似乎在使用一些非常旧的版本。
      2013-03-28 03:58:46Z
    6. 醇>

    我推荐开源乐器 通用影像加载器 。它最初基于Fedor Vlasov的项目 LazyList ,并且从那时起大大改进。

    • 多线程图像加载
    • 可以广泛调整ImageLoader的配置(线程执行器,下载器,解码器,内存和光盘缓存,显示图像选项等)
    • 图像缓存在内存和/或d中的可能性evice的文件系统(或SD卡)
    • “倾听”加载过程的可能性
    • 可以使用分开的选项自定义每个显示图像调用
    • 小工具支持
    • Android 2.0+支持

        
    546
    2014-08-28 23:19:24Z
    1. 如果你正在寻找它的创造者对待和维护的伟大的“图像加载”代码作为他的宝贝(不仅是一次性的解决方案),你只是找到它;大人物Nostra
      2012-03-29 11:12:20Z
    2. 非常出色的工作,但它略微落后于我的列表视图。如果你可以告诉最好的性能'ImageLoader'构建...或者可能是因为'DisplayImageOptions'。
      2012-10-21 16:58:26Z
    3. 我非常喜欢这个gridview,但我不能将它用于我的教程。我是android的初学者。我做了关于gridview的应用程序,但我的应用程序是targetSdkVersion 15所以我需要在后台线程中使用Asynctask进程。我以前使用这个gridview但它不起作用。我如何在targetSdkVersion 15?
      中使用它
      2012-10-25 07:30:52Z
    4. 您可以使用标签 [universal-image-loader]
      创建单独的问题
      2012-10-25 11:03:48Z
    5. 在阅读官方的android文档并尝试自己做这些东西后,我很确定这个库是最终所有图像加载的结尾。不能upvote足够。
      2013-12-30 18:06:55Z
    6. 醇>

    多线程性能,Gilles的教程Debunne。

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

    •  AsyncTasks
    • 坚硬,有限的尺寸,FIFO cache
    • 一个柔软,轻松的garbage collect-cache缓存。
    • 下载时占位符 Drawable

        
    154
    2014-03-13 11:45:30Z
    1. 但它建立在Android 2.2(Froyo)上......
      2011-02-03 10:04:23Z
    2. 它在2.1中工作正常。只是不要使用AndroidHttpClient。
      2011-02-05 02:22:08Z
    3. @ thomas-ahle谢谢,我看到AndroidHttpClient在2.1中给出了错误,因为它是从2.2实现的,但是并没有真正试图找到别的东西来替换它
      2011-02-09 08:02:54Z
    4. @Adina你是对的,我忘记了。但是,配方中没有任何东西可以用普通的HttpClient完成。
      2011-02-22 12:49:33Z
    5. 仍然是OOM ......
      2012-05-07 13:35:47Z
    6. 醇>

    更新:请注意,此答案现在非常无效。垃圾收集器对SoftReference和WeakReference采取积极行动,因此此代码不适合新的应用程序。(相反,请尝试使用通用图像加载器等库在其他答案中。)

    感谢James的代码,以及Bao-Long对使用SoftReference的建议。我在James的代码上实现了SoftReference的更改。不幸的是,SoftReferences导致我的图像垃圾收集过快。在我的情况下没有SoftReference的东西很好,因为我的列表大小有限,我的图像很小。

    一年前有关于Google群组的SoftReferences的讨论:链接到主题。作为过早垃圾收集的解决方案,他们建议使用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();
    }
    
        
    105
    2013-07-22 00:17:58Z
    1. 你可以创建像硬代和软代的代。你可以修复一个时间清除缓存将清除所有未在3秒内访问的图像..你可以看看谷歌货架项目
      2011-01-18 08:06:23Z
    2. 开发人员.android.com /reference /java /lang /ref /... SoftReference doc有关于缓存的说明,请参阅“避免缓存的软引用”部分。大多数应用程序应使用android.util.LruCache而不是软引用。
      2013-02-26 11:48:00Z
    3. 我很欣赏你的代码但是现在在新的Android O /S中有“积极的”垃圾收集。持有弱引用对我没有任何意义。
      2013-07-21 17:54:15Z
    4. @ j2emanue你是对的,因为我试图在答案的顶部指出,SoftReferences被垃圾收集得太快了。我会尝试编辑这个答案,使其更清晰。
      2013-07-22 00:13:50Z
    5. 醇>

    毕加索

    使用杰克沃顿的毕加索图书馆。 (一个完美的ImageLoading Library构成ActionBarSherlock的开发者)

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

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

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

    Picasso自动处理Android上图像加载的许多常见缺陷:

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

    Picasso Jake Wharton的图书馆

    滑翔强>

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

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

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

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

    Glide Image Loading Library

    Facebook的壁画

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

    Fresco负责图像加载和显示,因此您不必这样做。它将从网络加载图像,local存储或本地资源,并在图像到达之前显示占位符。它有两级缓存;一个在内存中,另一个在内部存储中。

    Fresco Github

    在Android 4.x及更低版本中,Fresco将图像放在Android内存的特殊区域。这样可以让您的应用程序运行得更快 - 并且更少经历可怕的OutOfMemoryError。

    Fresco文档

        
    93
    2015-08-11 18:02:34Z
    1. 毕加索是由Square开发的图书馆
      2018-05-16 21:03:32Z
    2. 醇>

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

    1. 我意识到使用drawables比使用位图更快,所以我使用drawables

    2. 使用SoftReference非常棒,但它会使缓存的图像被删除得太频繁,因此我添加了一个包含图像引用的链接列表,防止图像被删除,直到达到预定义的大小

    3. 要打开InputStream,我使用java.net.URLConnection,它允许我使用Web缓存(您需要先设置响应缓存,但这是另一个故事)

    4. 醇>

      我的代码:

       
      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;
      }
      }
      
          
    79
    2012-05-14 09:37:15Z
    1. 效果很好!顺便说一下,班级名称中有一个拼写错误。
      2011-12-07 14:25:06Z
    2. 如果它节省了其他人的时间: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;
      2012-01-08 05:01:58Z
    3. 非常感谢,这是一个很好的实现。我还为加载drawable时添加了一个不同的占位符,以便用户可以获得一些反馈。
      2012-02-07 15:53:55Z
    4. 我认为最好在executorService(mThreadPool)中使用LIFO队列而不是默认FIFO,以便加载所请求的最后图像(可能是可见的)第一。请参阅 stackoverflow.com/questions/4620061/how-to-创建-LIFO执行人
      2012-02-07 16:19:21Z
    5. @ MichaelReed,如果您是Eclipse用户,我建议使用Ctrl-Shift-O(字母O,而不是数字0)。它可以自动完成添加导入的过程并为您组织它们。如果您使用的是Mac,请改用Command-Shift-O。
      2012-03-20 15:21:45Z
    6. 醇>

    我已经关注了这个Android培训,我认为它在不阻止主UI的情况下下载图像方面表现非常出色。它还处理缓存和处理滚动浏览许多图像:有效加载大位图

        
    77
    2013-05-02 21:01:16Z
    1. 对不起,我只指出了Google IO应用程序的单个课程(我编辑时间太晚了)。你应该真的学习all他们的图像加载和缓存实用程序类,您可以在与缓存类相同的包中找到。
      2013-01-31 05:28:29Z
    2. 有人会建议从iosched app的util文件夹中获取DiskLruCache,Image * .java文件,以帮助处理列表视图的图像加载/缓存吗?我的意思是绝对值得关注这个主题的在线开发人员指南,但是这些类(来自iosched)对模式有了进一步的了解。
      2013-04-25 16:58:08Z
    3. 醇>

    1。 Picasso 允许在您的应用程序中加载无忧图像 - 通常只需一行代码!

    使用Gradle:

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

    只需一行代码!

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

    2。 Glide 图片加载适用于Android的缓存库专注于平滑滚动

    使用Gradle:

     
    repositories {
      mavenCentral() 
      google()
    }
    
    dependencies {
       implementation 'com.github.bumptech.glide:glide:4.7.1'
       annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
    }
    

    //对于简单的观点:

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

    3。 fresco 是一个强大的功能用于在Android中显示图像的系统    applications.Fresco负责图像加载和显示,所以你没有   到。

    壁画入门

        
    63
    2018-07-25 10:58:53Z
    1. 本教程可以为PICASOO提供更多帮助: - androidtutorialshub.com/... 和GLIDE: - androidtutorialshub.com/...
      2017-05-10 06:54:29Z
    2. 醇>

    我编写了一个教程,解释了如何在列表视图中对图像进行延迟加载。我详细介绍了回收和并发问题。我还使用固定的线程池来防止产生大量线程。

    在Listview教程中延迟加载图像

        
    51
    2013-07-04 20:40:56Z

    我这样做的方法是启动一个线程来在后台下载图像,并为每个列表项提供一个回调。当图像下载完成后,它会调用回调来更新列表项的视图。

    但是,当您回收视图时,此方法效果不佳。

        
    39
    2009-02-12 20:07:14Z
    1. 使用每个图像的线程也是我使用的方法。如果将模型与视图分开,则可以将模型保留在Activity之外(就像在“应用程序”类中一样)以保持缓存。如果您有许多图像,请注意资源不足。
      2009-02-15 00:40:11Z
    2. 请您详细说明。我是android开发的新手。感谢您提供的建议
      2009-02-15 14:23:55Z
    3. 开始每个图像的新线程不是一个有效的解决方案。你可以在内存中结束很多线程并冻结UI。
      2010-07-01 00:04:22Z
    4. Fedor,同意,我通常使用队列和线程池,这是最好的方式去imo。
      2010-07-04 22:48:08Z
    5. 醇>

    我只想添加一个更好的示例, XML Adapters 。因为它被谷歌使用,我也使用相同的逻辑来避免OutOfMemory错误。

    基本上这个ImageDownloader 是你的答案(因为它涵盖了你的大多数要求)。有些你也可以在那里实现。

        
    31
    2012-11-22 19:32:50Z
    1. ImageDownloader类未得到遵守:请参阅下面的解决方案 code.google.com/p/parleys-android-nextgen/issues/detail?id=1
      2012-02-04 04:48:55Z
    2. 试过这段代码,它给了我OOM
      2013-10-04 08:28:35Z
    3. 醇>

    我一直在使用新的Android Volley Library com.android.volley.toolbox.NetworkImageView中的NetworkImageView,它看起来效果很好。显然,这与 Google Play 和其他新Google应用程序中使用的视图相同。绝对值得一试。

    28
    2014-03-16 13:28:38Z
    1. 我认为这是最好的解决方案 - 其他答案都非常陈旧 - 凌空很快,并且与jake warthons disklrucache相结合是一个完美的解决方案 - 我尝试了很多其他但不是一个稳定而快速的凌空
      2014-09-07 22:19:10Z
    2. 醇>

    这是Android上的一个常见问题,许多人已经通过多种方式解决了这个问题。在我看来,我见过的最好的解决方案是名为 Picasso 的相对较新的库。 。以下是重点:

    • 开源,但由Jake Wharton ActionBarSherlock 成名。
    • 使用一行代码
    • 从网络或应用资源异步加载图像
    • 自动ListView检测
    • 自动磁盘和内存缓存
    • 可以进行自定义转换
    • 许多可配置的选项
    • 超级简单的API
    • 经常更新
    27
    2013-10-15 23:22:19Z

    嗯,来自互联网的图像加载时间有很多解决方案。您也可以使用图书馆 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;
    }
    

    应该解决你的延迟加载问题。

        
    25
    2015-04-24 21:10:00Z
    1. 对我来说很好,但需要一个Jar文件包含在你的项目中。你可以从这里下载那个JAR文件AQuery androidAQuery = new AQuery(this);链接是: code.google.com/archive/p/android-query/downloads
      2017-04-24 09:13:58Z
    2. 醇>

    我认为这个问题在Android开发人员中非常受欢迎,并且有很多这样的图书馆声称可以解决这个问题,但其中只有少数几个似乎已经出现了问题。 AQuery 就是这样一个图书馆,但它在各个方面都优于大多数图书馆。值得一试。

        
    24
    2014-03-16 13:19:04Z

    你必须尝试这种通用装载机是最好的。 在懒惰加载完成许多RnD之后我正在使用它。

    通用图像加载器

    功能强>

    • 多线程图像加载(异步或同步)
    • ImageLoader配置的广泛定制(线程执行器,下载器,解码器,内存和磁盘缓存,显示图像选项等)
    • 每个显示图像调用的许多自定义选项(存根图像,缓存切换,解码选项,位图处理和显示等)
    • 内存和/或磁盘(设备的文件系统或SD卡)上的图像缓存
    • 听取加载过程(包括下载进度)

    Android 2.0+支持

        
    21
    2015-02-05 12:45:50Z

    查看 Shutterbug ,Applidium的轻量级SDWebImage(iOS上的一个不错的库)到Android的端口。 它支持异步缓存,存储失败的URL,很好地处理并发,并包含有用的子类。

    欢迎拉取请求(和错误报告)!

        
    20
    2012-11-02 17:42:16Z

    DroidParts ImageFetcher ,需要零配置才能开始。

    • 使用磁盘和放大器内存中最近最少使用(LRU)缓存。
    • 有效解码图像。
    • 支持在后台线程中修改位图。
    • 简单的交叉淡化。
    • 图片加载进度回调。

    克隆 DroidPartsGram 以获取示例:

        
    16
    2014-03-16 13:26:19Z
    1. 嗨,我看过代码示例,但是我在使用带有ArrayAdapter的ImageFetcher时遇到了问题,你介意看看我的问题吗? stackoverflow.com/questions/21089147 /... 谢谢=]
      2014-01-13 10:37:02Z
    2. 醇>

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

    有四种基本方式。

    1. DIY =&gt;不是最好的解决方案,但对于一些图像,如果你想没有使用其他库的麻烦

    2. Volley的Lazy Loading库=&gt;来自android的人。它很好,但是文档记录很少,因此使用起来很困难。

    3. Picasso:一个简单的解决方案,你甚至可以指定你想要引入的确切图像大小。它使用起来非常简单,但对于必须处理的应用程序可能不是很“高效”大量的图像。

    4. UIL:延迟加载图片的最佳方式。您可以缓存图像(当然需要权限),初始化加载程序一次,然后完成工作。到目前为止我见过的最成熟的异步图像加载库。

    16
    2015-12-02 05:23:43Z

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

    他们的图书馆在Github上托管这里,他们有一个非常活跃的问题跟踪器。他们的项目似乎也相当活跃,在撰写此回复时提交了超过300次。

        
    15
    2013-01-12 11:00:25Z
    1. 实际上Novoda是一个很棒的图书馆但是...有时你不需要一个庞大的图书馆,只需要一个简单的解决方案。这就是为什么Github中的LazyList非常好,如果你的应用只在listView中显示图像并且不是你应用的主要功能,那么我更喜欢使用更轻松的东西。否则,如果您知道必须经常使用并且是核心的一部分,请尝试Novoda。
      2013-04-15 15:34:20Z
    2. 醇>

    检查我的 LazyList 的分支。基本上,我通过延迟ImageView的调用来改进LazyList并创建两个方法:

    1. 当您需要输入“正在加载图片......”
    2. 之类的内容时
    3. 当您需要显示下载的图像时。
    4. 醇>

      我还通过在此对象中实施单身人士来改进了ImageLoader。

          
    13
    2014-03-16 13:24:50Z

    以上所有代码都有自己的价值,但根据我的个人经验,只需尝试毕加索。

    Picasso 是专门用于此目的的库,实际上它将自动管理缓存和所有其他网络操作。您必须在项目中添加库并只编写一行代码从远程URL加载图像。

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

        
    11
    2015-09-26 18:54:20Z

    如果你想显示像Facebook这样的Shimmer布局,那么就有一个官方的facebook库。 FaceBook Shimmer 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'
    

    以下是它的样子。

        
    11
    2019-05-05 06:17:57Z

    使用滑动库。它对我有用,也适用于你的代码。它既适用于图像,也适用于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);
    }
    
        
    9
    2017-03-16 10:11:09Z

    我可以推荐一种不同于魅力的方式:Android查询。

    您可以从 JAR 文件: //code.google.com/p/android-query/downloads/list"rel =“nofollow”>此处

     
    AQuery androidAQuery = new AQuery(this);
    

    举个例子:

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

    它非常快速和准确,使用它你可以找到更多的功能,如加载时的动画,获取位图(如果需要)等。

        
    7
    2014-03-16 13:36:00Z

    尝试 Aquery 。它具有非常简单的方法来异步加载和缓存图像。

        
    7
    2014-03-16 13:37:22Z

    URLImageViewHelper 是一个非常棒的图书馆,可以帮助您实现这一目标。

        
    7
    2014-03-16 13:37:45Z
     
    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;
     }
    }
    
        
    4
    2013-10-21 12:21:40Z

    我遇到了这个问题并实施了lruCache。我相信您需要API 12及更高版本或使用兼容性v4库。 lurCache是​​快速内存,但它也有预算,所以如果你担心你可以使用diskcache ......这些都在 缓存位图

    我现在将提供我的实现,即 singleton ,我可以从以下任何地方拨打电话:

     
    //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);
            }
        }
    }
    
        
    4
    2014-03-16 13:34:56Z
来源放置 这里