Android实现图片异步加载及本地缓存

在android项目中访问网络图片是非常普遍性的事情,如果我们每次请求都要访问网络来获取图片,会非常耗费流量,而且图片占用内存空间也比较大,图片过多且不释放的话很容易造成内存溢出。针对上面遇到的两个问题,首先耗费流量我们可以将图片第一次加载上面缓存到本地,以后如果本地有就直接从本地加载。图片过多造成内存溢出,这个是最不容易解决的,要想一些好的缓存策略,比如大图片使用LRU缓存策略或懒加载缓存策略,首先介绍一下本地缓存图片。

首先看一下异步加载缓存本地代码:

public class AsyncBitmapLoader
{
 /**
  * 内存图片软引用缓冲
  */
 private HashMap<String, SoftReference<Bitmap>> imageCache = null; 

 public AsyncBitmapLoader()
 {
  imageCache = new HashMap<String, SoftReference<Bitmap>>();
 } 

 public Bitmap loadBitmap(final ImageView imageView, final String imageURL, final ImageCallBack imageCallBack)
 {
  //在内存缓存中,则返回Bitmap对象
  if(imageCache.containsKey(imageURL))
  {
   SoftReference<Bitmap> reference = imageCache.get(imageURL);
   Bitmap bitmap = reference.get();
   if(bitmap != null)
   {
    return bitmap;
   }
  }
  else
  {
   /**
    * 加上一个对本地缓存的查找
    */
   String bitmapName = imageURL.substring(imageURL.lastIndexOf("/") + 1);
   File cacheDir = new File("/mnt/sdcard/test/");
   File[] cacheFiles = cacheDir.listFiles();
   int i = 0;
   if(null!=cacheFiles){
   for(; i<cacheFiles.length; i++)
   {
    if(bitmapName.equals(cacheFiles[i].getName()))
    {
     break;
    }
   } 

   if(i < cacheFiles.length)
   {
    return BitmapFactory.decodeFile("/mnt/sdcard/test/" + bitmapName);
   }
   }
  } 

  final Handler handler = new Handler()
  {
   /* (non-Javadoc)
    * @see android.os.Handler#handleMessage(android.os.Message)
    */
   @Override
   public void handleMessage(Message msg)
   {
    // TODO Auto-generated method stub
    imageCallBack.imageLoad(imageView, (Bitmap)msg.obj);
   }
  }; 

  //如果不在内存缓存中,也不在本地(被jvm回收掉),则开启线程下载图片
  new Thread()
  {
   /* (non-Javadoc)
    * @see java.lang.Thread#run()
    */
   @Override
   public void run()
   {
    // TODO Auto-generated method stub
    InputStream bitmapIs = HttpUtils.getStreamFromURL(imageURL); 

    Bitmap bitmap = BitmapFactory.decodeStream(bitmapIs);
    imageCache.put(imageURL, new SoftReference<Bitmap>(bitmap));
    Message msg = handler.obtainMessage(0, bitmap);
    handler.sendMessage(msg); 

    File dir = new File("/mnt/sdcard/test/");
    if(!dir.exists())
    {
     dir.mkdirs();
    } 

    File bitmapFile = new File("/mnt/sdcard/test/" +
      imageURL.substring(imageURL.lastIndexOf("/") + 1));
    if(!bitmapFile.exists())
    {
     try
     {
      bitmapFile.createNewFile();
     }
     catch (IOException e)
     {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
    FileOutputStream fos;
    try
    {
     fos = new FileOutputStream(bitmapFile);
     bitmap.compress(Bitmap.CompressFormat.PNG,
       100, fos);
     fos.close();
    }
    catch (FileNotFoundException e)
    {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
    catch (IOException e)
    {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  }.start(); 

  return null;
 } 

 public interface ImageCallBack
 {
  public void imageLoad(ImageView imageView, Bitmap bitmap);
 }
} 

这是一个封装好的异步加载图片类,缓存了两份,一份是使用软引用缓存到内存中,一份是缓存到本地sd卡,如果内存中没有,则从本地查找,如果本地没有则从网络获取图片。

public class HttpUtils { 

 public static InputStream getStreamFromURL(String imageURL) {
  InputStream in=null;
  try {
   URL url=new URL(imageURL);
   HttpURLConnection connection=(HttpURLConnection) url.openConnection();
   in=connection.getInputStream(); 

  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return in; 

 }
} 

这是一个访问网络获取类,不细说了。
   下面看一下如何使用封装好的异步加载图片的类:

public class ImageCacheActivity extends Activity {
 /** Called when the activity is first created. */
 private ListView listview;
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main); 

  listview=(ListView) findViewById(R.id.listView_list);
  MyAdapter adapter=new MyAdapter();
  listview.setAdapter(adapter);
 } 

 private class MyAdapter extends BaseAdapter{ 

  private AsyncBitmapLoader asyncBitmapLoader;
  public MyAdapter(){
   asyncBitmapLoader=new AsyncBitmapLoader();
  }
  @Override
  public int getCount() {
   // TODO Auto-generated method stub
   return 10;
  } 

  @Override
  public Object getItem(int position) {
   // TODO Auto-generated method stub
   return null;
  } 

  @Override
  public long getItemId(int position) {
   // TODO Auto-generated method stub
   return 0;
  } 

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
   // TODO Auto-generated method stub
   if(convertView==null){
    convertView=LayoutInflater.from(getApplicationContext()).inflate(R.layout.list_item, null);
   }
   ImageView image=(ImageView) convertView.findViewById(R.id.addexam_list_icon);
   String imageURL="http://s.ata.net.cn/4f98db46908987a21a000003/logo/2012/04/114_80aaf295c083d07a496743699aac3193.png";
   Bitmap bitmap=asyncBitmapLoader.loadBitmap(image, imageURL, new ImageCallBack() { 

    @Override
    public void imageLoad(ImageView imageView, Bitmap bitmap) {
     // TODO Auto-generated method stub
     imageView.setImageBitmap(bitmap);
    }
   });
    if(bitmap == null)
    {
     image.setImageResource(R.drawable.ic_launcher);
    }
    else
    {
     image.setImageBitmap(bitmap);
    } 

   return convertView;
  } 

 }
} 

这样就完成了,网络获取不到bitmap则显示默认图片。

这是一种很实用的方法,大家自己试试吧!

希望本文所述对大家学习Android软件编程有所帮助。

(0)

相关推荐

  • Android实现图片异步加载并缓存到本地

    在android应用开发的时候,加载网络图片是一个非常重要的部分,很多图片不可能放在本地,所以就必须要从服务器或者网络读取图片. 软引用是一个现在非常流行的方法,用户体验比较好,不用每次都需要从网络下载图片,如果下载后就存到本地,下次读取时首先查看本地有没有,如果没有再从网络读取. 下面就分享一下异步加载网络图片的方法吧. FileCache.java import java.io.File; import android.content.Context; public class FileCa

  • Android异步下载图片并且缓存图片到本地DEMO详解

    在Android开发中我们经常有这样的需求,从服务器上下载xml或者JSON类型的数据,其中包括一些图片资源,本demo模拟了这个需求,从网络上加载XML资源,其中包括图片,我们要做的解析XML里面的数据,并且把图片缓存到本地一个cache目录里面,并且用一个自定义的Adapter去填充到LIstView,demo运行效果见下图: 通过这个demo,要学会有一下几点 1.怎么解析一个XML 2.demo中用到的缓存图片到本地一个临时目录的思想是怎样的? 3.AsyncTask类的使用,因为要去异

  • Android图片三级缓存策略(网络、本地、内存缓存)

    一.简介 现在的Android应用程序中,不可避免的都会使用到图片,如果每次加载图片的时候都要从网络重新拉取,这样不但很耗费用户的流量,而且图片加载的也会很慢,用户体验很不好.所以一个应用的图片缓存策略是很重要的.通常情况下,Android应用程序中图片的缓存策略采用"内存-本地-网络"三级缓存策略,首先应用程序访问网络拉取图片,分别将加载的图片保存在本地SD卡中和内存中,当程序再一次需要加载图片的时候,先判断内存中是否有缓存,有则直接从内存中拉取,否则查看本地SD卡中是否有缓存,SD

  • Android远程获取图片并本地缓存

    对于客户端--服务器端应用,从远程获取图片算是经常要用的一个功能,而图片资源往往会消耗比较大的流量,对应用来说,如果处理不好这个问题,那会让用户很崩溃,不知不觉手机流量就用完了,等用户发现是你的应用消耗掉了他手机流量的话,那么可想而知你的应用将面临什么样的命运. 另外一个问题就是加载速度,如果应用中图片加载速度很慢的话,那么用户同样会等到崩溃. 那么如何处理好图片资源的获取和管理呢? *异步下载 *本地缓存 1.异步下载: 大家都知道,在android应用中UI线程5秒没响应的话就会抛出无响应异

  • android异步加载图片并缓存到本地实现方法

    在android项目中访问网络图片是非常普遍性的事情,如果我们每次请求都要访问网络来获取图片,会非常耗费流量,而且图片占用内存空间也比较大,图片过多且不释放的话很容易造成内存溢出.针对上面遇到的两个问题,首先耗费流量我们可以将图片第一次加载上面缓存到本地,以后如果本地有就直接从本地加载.图片过多造成内存溢出,这个是最不容易解决的,要想一些好的缓存策略,比如大图片使用LRU缓存策略或懒加载缓存策略.今天首先介绍一下本地缓存图片. 首先看一下异步加载缓存本地代码: 复制代码 代码如下: public

  • Android使用缓存机制实现文件下载及异步请求图片加三级缓存

    首先给大家介绍Android使用缓存机制实现文件下载 在下载文件或者在线浏览文件时,或者为了保证文件下载的正确性,需要使用缓存机制,常使用SoftReference来实现. SoftReference的特点是它的一个实例保存对一个Java对象的软引用,该软引用的存在不妨碍垃圾收集线程对该Java对象的回收.也就是说,一旦SoftReference保存了对一个Java对象的软引用后,在垃圾线程对这个Java对象回收前,SoftReference类所提供的get()方法返回Java对象的强引用.另外

  • Android实现图片异步加载及本地缓存

    在android项目中访问网络图片是非常普遍性的事情,如果我们每次请求都要访问网络来获取图片,会非常耗费流量,而且图片占用内存空间也比较大,图片过多且不释放的话很容易造成内存溢出.针对上面遇到的两个问题,首先耗费流量我们可以将图片第一次加载上面缓存到本地,以后如果本地有就直接从本地加载.图片过多造成内存溢出,这个是最不容易解决的,要想一些好的缓存策略,比如大图片使用LRU缓存策略或懒加载缓存策略,首先介绍一下本地缓存图片. 首先看一下异步加载缓存本地代码: public class AsyncB

  • Android图片异步加载框架Android-Universal-Image-Loader

    Android-Universal-Image-Loader是一个图片异步加载,缓存和显示的框架.这个框架已经被很多开发者所使用,是最常用的几个Android开源项目之一,主流的应用,随便反编译几个,都可以见到它的身影.淘宝,天猫,Facebook,京东商城等都用到了这个项目. 该项目的Github地址链接 运行流程: 每一个图片的加载和显示任务都运行在独立的线程中,除非这个图片缓存在内存中,这种情况下图片会立即显示.如果需要的图片缓存在本地,它会开启一个独立的线程队列.如果在缓存中没有正确的图

  • Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案

    Android ListView异步加载图片错位.重复.闪烁分析以及解决方案,具体问题分析以及解决方案请看下文. 我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如ListView上有100个Item,一屏只显示10个Item,我们知道getView()中convertView是用来复用View对象的,因为一个Item的对应一个View对象,而Ima

  • Android实现ListView异步加载图片的方法

    本文实例讲述了Android实现ListView异步加载图片的方法.分享给大家供大家参考.具体如下: ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,不用让用户等待下去,下面就说实现方法,先贴上主方法的代码: package cn.wangmeng.test; import java.io.IOException; import java.io.InputStream; import java.lang.ref.SoftReferen

  • Android实现Listview异步加载网络图片并动态更新的方法

    本文实例讲述了Android实现Listview异步加载网络图片并动态更新的方法.分享给大家供大家参考,具体如下: 应用实例:解析后台返回的数据,把每条都显示在ListView中,包括活动图片.店名.活动详情.地址.电话和距离等. 在布局文件中ListView的定义: <ListView android:id="@id/maplistview" android:background="@drawable/bg" android:layout_width=&qu

  • Android实现ListView异步加载的方法(改进版)

    本文实例讲述了Android实现ListView异步加载的方法.分享给大家供大家参考,具体如下: @Override public View getView(int position, View convertView, ViewGroup parent) { ---- ViewHolder VH = null; ---- VH.mImageView.setTag(position); VH.mThumb.setImageDrawable(imageLoader.loadDrawable(pos

  • Android App中实现图片异步加载的实例分享

    一.概述 一般大量图片的加载,比如GridView实现手机的相册功能,一般会用到LruCache,线程池,任务队列等:那么异步消息处理可以用哪呢? 1.用于UI线程当Bitmap加载完成后更新ImageView 2.在图片加载类初始化时,我们会在一个子线程中维护一个Loop实例,当然子线程中也就有了MessageQueue,Looper会一直在那loop停着等待消息的到达,当有消息到达时,从任务队列按照队列调度的方式(FIFO,LIFO等),取出一个任务放入线程池中进行处理. 简易的一个流程:当

  • 在Android的应用中实现网络图片异步加载的方法

    前言 其实很幸运,入职一周之后就能跟着两个师兄做android开发,师兄都是大神,身为小白的我只能多多学习,多多努力.最近一段时间都忙的没机会总结,今天刚完成了android客户端图片异步加载的类,这里记录一下(ps:其实我这里都是参考网上开源实现) 原理 在ListView或者GridView中加载图片的原理基本都是一样的: 先从内存缓存中获取,取到则返回,取不到进行下一步     从文件缓存中获取,取到则返回并更新到内存缓存,取不到则进行进行下一步     从网络上下载图片,并更新内存缓存和

  • Android异步加载数据和图片的保存思路详解

    把从网络获取的图片数据保存在SD卡上, 先把权限都加上 网络权限 android.permission.INTERNET SD卡读写权限 android.permission.MOUNT_UNMOUNT_FILESYSTEMS android.permission.WRITE_EXTERNAL_STORAGE 总体布局 写界面,使用ListView,创建条目的布局文件,水平摆放的ImageView TextView 在activity中获取到ListView对象,调用setAdapter()方法

随机推荐