广

android开发

  • IOS开发
  • android开发
  • PHP编程
  • JavaScript
  • ASP.NET
  • ASP编程
  • JSP编程
  • Java编程
  • 易语言
  • Ruby编程
  • Perl编程
  • AJAX
  • 正则表达式
  • C语言
  • 编程开发

    ListView异步加载图片实现思路

    2018-04-06 10:41:38 次阅读 稿源:互联网
    广告
    在应用开发中,经常用到ListView去加载数据,加载图片和文字是比较常见的,文字还好,图片从网络请求加载速度比较慢,所以需要把图片的加载放到另一个线程中去执行,执行完了再更新UI线程。以下列出一个我在项目中使用到的异步加载图片的解决方案,代码没有上全,给出核心部分。

    大致思路是这样
    1.利用软引用来缓存图片Bitmap,用图片的URL作为缓存查找的Key;
    2.设两级缓存,一级是SoftReference,二级是本地SD卡;
    3.如果两级缓存都没取到图片,则从服务器获取,并加入缓存;
    4.加载完后通过回调接口通知UI更新;

    以下是异步加载的关键代码,其中一些工具类没有给出,自己实现就可以,比如HttpRequest是我自己写的一个类。
    代码如下:

    public class AsyncImageLoader {
    //Cache for image(Type String is the URL of image,the second parameter is soft reference)
    private HashMap<String, SoftReference<Bitmap>> imageCache = null;
    private Activity context;
    public AsyncImageLoader(Activity context){
    this.context = context;
    imageCache = new HashMap<String, SoftReference<Bitmap>>();
    }
    public Bitmap loadImage(final ImageView imageView,final String imageURL,final ImageCallBack imageCallBack){
    //If the cache contains the reference of bitmap then return
    if (imageCache.containsKey(imageURL)) {
    SoftReference<Bitmap> bitmapReference = imageCache.get(imageURL);
    Bitmap bitmap = bitmapReference.get();
    if (bitmap != null) {
    return bitmap;
    }
    }
    //Second cache,search local SD card
    else {
    String fileName = StringUtil.namePicture(imageURL);//获取文件名
    boolean isExist = SystemUtils.findPhotoFromSDCard(Constant.INFO_PATH, fileName);
    if (isExist) {//是否在SD卡存在图片
    Bitmap bitmap = SystemUtils.getPhotoFromSDCard(Constant.INFO_PATH, fileName);
    return bitmap;
    }
    }
    final Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg)
    {
    imageCallBack.setImage(imageView, (Bitmap)msg.obj);
    }
    };
    //If the bitmap not exists in cache or SD card,then get it from net
    new Thread(){
    @Override
    public void run() {
    // TODO Auto-generated method stub
    boolean isNetwork = SystemUtils.checkNetwork(context);
    if (isNetwork) {
    InputStream photoStream = HttpRequest.getImageStream(imageURL);//这里是我自己写的一个类,目的是通过URL地址从服务器获取图片输入流
    Bitmap bitmap;
    try {
    bitmap = ImageTools.getResizeBitmap(photoStream, 128, 128);
    if (bitmap != null) {
    String fileName = StringUtil.namePicture(imageURL);
    //Save image to SD card
    SystemUtils.savePhotoToSDCard(bitmap, fileName, Constant.INFO_PATH);
    //Put soft reference to cache
    imageCache.put(imageURL, new SoftReference<Bitmap>(bitmap));
    //Send message to update UI
    Message message = myHandler.obtainMessage(0, bitmap);
    myHandler.sendMessage(message);
    }
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    }.start();
    return null;
    }
    /**
    * Interface for load image
    * @author Ryan
    *
    */
    public interface ImageCallBack{
    //Set image for imageview through bitmap
    public void setImage(ImageView imageView,Bitmap bitmap);
    }
    }

    在ListView的adapter的getView方法中:
    代码如下:

    Bitmap bitmap1 = asyncImageLoader.loadImage(viewHolder.imageView1, url1, new ImageCallBack() {
    @Override
    public void setImage(ImageView imageView, Bitmap bitmap) {
    // TODO Auto-generated method stub
    imageView.setImageBitmap(bitmap);
    }
    });
    if (bitmap1 != null) {
    viewHolder.imageView1.setImageBitmap(bitmap1);
    }else {
    viewHolder.imageView1.setImageResource(R.drawable.image_bg);
    }

    其中asyncImageLoader是在adapter的构造方法中初始化的,形成一个缓存。通过这个机制就可以实现ListView的图片异步加载,在用户体验上比直接加载要感觉好很多,那样会造成界面卡顿。这里是加载一张图片的情况,如果ListView的item中的图片是不定的,有可能是一张、两张、三张,该用什么方式呢,大家可以思考一下,并可以一起讨论一下,包括实现ListView滚动时不加载数据也是优化ListView加载的必要步骤。

    一起学吧部分文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与一起学吧进行文章共享合作。

    广告
    广告
    广告