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则显示默认图片。


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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值