?
在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)???
- [email protected]#handleMessage(android.os.Message)???
- ?????????????*/????
- [email protected]
- ????????????public?void?handleMessage(Message?msg)????
- ????????????{????
- ????????????????//?TODO?Auto-generated?method?stub????
- ????????????????imageCallBack.imageLoad(imageView,?(Bitmap)msg.obj);????
- ????????????}????
- ????????};????
- ????????????
- ????????//如果不在内存缓存中,也不在本地(被jvm回收掉),则开启线程下载图片????
- ????????new?Thread()????
- ????????{????
- ????????????/*?(non-Javadoc)???
- [email protected]#run()???
- ?????????????*/????
- [email protected]
- ????????????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;??
- [email protected]
- ????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();??
- ????????}??
- [email protected]
- ????????public?int?getCount()?{??
- ????????????//?TODO?Auto-generated?method?stub??
- ????????????return?10;??
- ????????}??
- ??
- [email protected]
- ????????public?Object?getItem(int?position)?{??
- ????????????//?TODO?Auto-generated?method?stub??
- ????????????return?null;??
- ????????}??
- ??
- [email protected]
- ????????public?long?getItemId(int?position)?{??
- ????????????//?TODO?Auto-generated?method?stub??
- ????????????return?0;??
- ????????}??
- ??
- [email protected]
- ????????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()?{??
- ??????????????????
- [email protected]
- ????????????????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则显示默认图片。
?
?
这是一种很实用的方法,大家自己试试吧!