我用一个 ListView 显示了一些图片和文字说明与这些图像。我得到的图像从互联网上。有没有办法懒载的图像,因此,虽然该文本显示,不锁和图像显示为他们被下载?

总的图像数量不是固定的。

有帮助吗?

解决方案

下面是我创建的认为,我的应用程序正在显示图像。请注意,在使用“日志”对象这里是围绕内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();
    }
}

其他提示

我发懒惰列表(位于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图像以减少内存消耗。我还尝试正确处理再循环的观点。

“替代文字”

我建议开放源码器 普遍的图像装载机.它最初是根据尔弗拉索夫的项目 LazyList 并已大大改进。

  • 多线程的图片加载
  • 可能广泛的调ImageLoader的配置(线的遗嘱执行人,downlaoder、解码器、存储器和光盘缓,显示图像的选择,和其他人)
  • 可能性的图像缓存在存和/或设备的文件系(或SD卡)
  • 可以"听"加载过程
  • 可能来自每一个显示器的图像话与分离的选项
  • 部件的支持
  • 安卓2.0+支持

多线程的性能, 一教程通过吉尔Debunne.

这是从安卓开发人员的博客。建议的代码用途:

  • AsyncTasks.
  • 坚硬的、规模有限, FIFO cache.
  • 一个柔软易 garbage collect-ed缓存。
  • 一个 占位 Drawable 虽然你下载。

enter image description here

更新:注意,这个答案是非常无效。垃圾回收行为的积极SoftReference和WeakReference,所以这些代码,是不适合用于新的应用程序。 (而是,试图库喜欢 普遍的图像装载机 建议在其他的答案。)

由于詹姆斯的代码,宝长的建议的使用SoftReference.我实施的SoftReference变化对詹姆斯的代码。不幸的是SoftReferences引起我的影像是垃圾收集的太快。在我的情况下,它是好的,而不SoftReference的东西,因为我的名单的尺寸是有限的,我的图片都很小。

有一个讨论从一年前关于SoftReferences在谷歌组: 链接线.作为解决太-早期的垃圾收集,他们建议的可能性手动设置VM堆尺寸使用安装.系统。VMRuntime.setMinimumHeapSize(),这是不是很吸引我.

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();
}

<强>毕加索

使用杰克沃顿商学院的毕加索库。 (A完美ImageLoading库形成ActionBarSherlock的显影剂)

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

图片急需上下文和视觉风格添加到Android应用。毕加索允许无障碍的图像加载在您的应用程序通常在一个代码行!

Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
在Android图像加载的

许多常见的陷阱被毕加索自动处理:

处理ImageView的回收和下载消除在适配器。 复杂的图像转换以最小的内存使用。 自动内存和磁盘高速缓存。

毕加索杰克脐带库

<强>滑翔

滑翔是Android快速且高效的开源媒体管理框架,它包装媒体解码,存储器和磁盘高速缓存,和资源池成一个简单的和易于使用的界面。

滑翔支持取,解码和显示视频剧照,图像和动画GIF。滑翔包括柔性的API,允许开发者插入到几乎任何网络堆栈。默认情况下,滑翔使用基于定制HttpURLConnection的堆栈,而且还包括工具库插上了谷歌的排球项目或广场的OkHttp库,而不是。

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

滑翔的主要焦点是使滚动任何种类的图像作为光滑和快地的列表,但滑翔也是有效的几乎在需要取出,调整大小和显示远程图像的任何情况下。

滑翔图像加载库

<强>壁画被Facebook

壁画是用于Android应用程序显示图像的强大的系统。

壁画照顾图像加载和显示的,所以你不必。它将从网络,本地存储,或本地资源加载图像,并显示一个占位符直到图像已经到来。它具有高速缓存的两个级别;一个在存储器中并在另一个内部存储。

壁画Github上

在的Android 4.x和下部,壁画使图像的Android存储器的特殊区域。这可以让你的应用程序运行速度更快 - 而且往往更遭受了可怕的OutOfMemoryError

壁画文档

高性能的装载后审查的方法提出这里, 我用 Ben的解决方案 有一些变化-

  1. 我意识到,工作与可绘为快这位图所以我使用可绘而不是

  2. 使用SoftReference是巨大的,但它使得缓存的图像将被删除过于频繁,所以我加了一个链接清单持有的图像引用,防止从图像被删除,直到它达到一个预先定义的尺寸

  3. 打开输入流我用爪哇。网。URLConnection允许我使用网页高速缓冲存储器(你需要设置一个响应缓第一,但这是另一个故事)

我的代码:

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

我按照这个Android的训练,我认为它在下载图像,而不会阻塞主UI出色。它还处理缓存和处理过许多图片滚动:装载大位图高效

<强> 1 毕加索 允许轻松的图像加载在您的应用程序通常在一个代码行!

使用摇篮:

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

的代码只是一个线路!

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

<强> 2 滑翔 一种图像加载和Android的缓存库集中于平滑滚动

使用摇篮:

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 壁画 是一个功能强大的系统,用于在Android的显示图像    applications.Fresco照顾图像加载和显示的,所以你不必   到。

入门壁画

我写了一个教程,说明如何做到图像的延迟加载在ListView。我进入有关回收和并发的问题的一些细节。我也使用一个固定的线程池,以防止产卵大量线程。

在列表视图教程<图像的延迟加载/ A>

我做的方式是通过启动一个线程下载图像的背景,并把它的每个列表项的回调。当图像被下载完它调用更新列表项的看法回调。

当你不过回收的意见这种方法并不能很好地工作。

我只想多加一个很好的例子,的 XML适配器 。因为它是使用谷歌,我也用同样的逻辑,以避免内存不足错误。

基本上这ImageDownloader 是你的答案(因为它涵盖了大部分的要求)。有些还可以实现在。

我一直在使用NetworkImageView从新安卓排库 com.android.volley.toolbox.NetworkImageView, 和这似乎是工作得很好。显然,这是相同的看法,即是使用 谷歌玩 和其他谷歌新的应用程序。绝对值得检查。

这是一个常见的问题上,这已经解决在许多方面通过的许多人。在我看来,最好的解决方案,我们看到的是相对较新的库被称为 毕加索.这里的要点:

  • 开放源,但由 Jake WhartonActionBarSherlock 名声。
  • 异步加载图像从网络或应用程序的资源与一行代码
  • 自动 ListView 检测
  • 自动盘和记忆缓存
  • 可以做的定义转变
  • 很多的配置的选择
  • 超级简单API
  • 经常更新

好了,从网上图片加载时间有很多的解决方案。您也可以使用该库 Android的查询。它会给你所有需要的活动。确保你想要做的和阅读的图书馆维基页面做什么。并解决图像加载限制。

这是我的代码:

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

这应该解决您的懒加载的问题。

我认为这个问题是Android开发中非常流行,而且有很多声称可以解决这个问题这样的库,但只有少数人似乎是上的标记。 AQuery 是一个这样的库,但它在各方面比大多数人好,是值得尝试。

你必须尝试这种普遍的加载程序是最好的。我用这个之后做了很多轮上的延迟加载。

普遍的图像装载机

功能

  • 多线程的图片加载(或异步同步)
  • 广泛的定制的ImageLoader的配置(线的遗嘱执行人,下载网站、解码器、存储器和磁盘缓,显示图像的选择,等等。)
  • 许多定制选项对于每一个显示器的图像话(stub图像、高速缓存交换机、解码的选择、位处理和显示,等等。)
  • 像高速缓存在存和/或磁盘上(设备的文件系统或SD卡)
  • 听装入过程(包括下载进展)

安卓2.0+支持

enter image description here

看一看摄影爱好者,Applidium团队的轻量级SDWebImage(iOS上的一个不错的库)端口到Android。 它支持异步缓存,存储失败的URL,处理并发井,和有用的亚类都包括在内。

引入请求(和错误报告)都热烈欢迎!

DroidPartsImageFetcher 需要零配置开始。

  • 使用磁盘和存储器 最近使用过的 (LRU)高速缓存。
  • 有效地解码图像。
  • 支持修改位图在背景线。
  • 有简单的横褪色。
  • 具有图像装进步回调。

克隆 DroidPartsGram 对于一个例子:

Enter image description here

只是一个快速尖端的人在犹豫不决,关于什么图书馆使用延迟装载的图片:

有四种基本方式。

  1. DIY=>不是最好的解决方案,但一些图像,如果你想去而无需使用其他图书馆

  2. 排球是懒载入图书馆=>从人在序。它是好的,一切,但是缺乏记录,因此是一个问题使用。

  3. 毕加索:一个简单的解决方案,只是工作时,你甚至可以指定确切的图像你想要的大小。这是非常简单的使用,但可能不是非常"高"为应用程序,必须处理的堆积如山的数量的图像。

  4. UIL:最好的方式来懒载的图像。你可以缓存图像(你需要许可的程),初始化装载程序一旦,然后你所做的工作。最成熟的步的图像图书馆加载我曾经见过这么远。

Novoda也有很大的懒图像加载库和许多应用程序,如Songkick的,波迪奥,SecretDJ和图片搜索使用他们的库。

这里在Github上

他们的图书馆托管,他们有一个非常活跃的问题跟踪为好。他们的项目似乎是相当积极的也有超过300多家承诺在写这篇答复的时间。

检查我的叉子的 LazyList.基本上,我提高LazyList通过延迟的呼吁图片视图,建立两个方法:

  1. 当你需要把一些东西像"装载图像..."
  2. 当你需要展示下载的图像。

我还改进了ImageLoader通过实施一个 单独 在这个对象。

以上所有的代码都有自己的价值,但我个人的经验,只是给毕加索一试。

毕加索是一个专门为此库中,实际上将管理缓存和所有其他网络运营automatically.You将不得不在你的项目中添加库,只是写一行代码从远程URL加载图像。

请点击这里查看:的http://代码.tutsplus.com /教程/ Android的SDK-工作与 - 毕加索 - CMS-22149

如果你想显示微光布局像Facebook存在的一个官方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截图”

使用滑行库。它为我工作,并为您的代码too.It两个图像,以及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);
}

我可以推荐一个不同的方式,就像一个魅力:安卓查询。

你可以下载, 罐子 文件从 在这里,

AQuery androidAQuery = new AQuery(this);

作为一个例子:

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

它的速度非常快和准确,并使用这个你可以找到更多的功能喜欢动画加载时,得到一个位图(如需要),等等。

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

URLImageViewHelper 是一个惊人的图书馆,可以帮助你做到这一点。

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

我有这个问题和实现lruCache.我相信你需要API12和上或使用的兼容性v4图书馆。lurCache是快速存储器,但它也有一个预算,所以,如果你担心这可以使用diskcache...这是所有的描述 缓位图.

我现在将提供执行其是 单独 我呼吁从任何地方这样的:

//Where the first is a string and the other is a imageview to load.

DownloadImageTask.getInstance().loadBitmap(avatarURL, iv_avatar);

这里是理想的代码,以缓和然后打电话给上述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);
        }
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top