zoukankan      html  css  js  c++  java
  • android异步加载图片并缓存到本地实现方法

    图片过多造成内存溢出,这个是最不容易解决的,要想一些好的缓存策略,比如大图片使用LRU缓存策略或懒加载缓存策略。今天首先介绍一下本地缓存图片。

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

    复制代码代码如下:

    publicclassAsyncBitmapLoader 

    /** 
    *内存图片软引用缓冲 
    */ 
    privateHashMap<String,SoftReference<Bitmap>>imageCache=null; 
    publicAsyncBitmapLoader() 

    imageCache=newHashMap<String,SoftReference<Bitmap>>(); 

    publicBitmaploadBitmap(finalImageViewimageView,finalStringimageURL,finalImageCallBackimageCallBack) 

    //在内存缓存中,则返回Bitmap对象 
    if(imageCache.containsKey(imageURL)) 

    SoftReference<Bitmap>reference=imageCache.get(imageURL); 
    Bitmapbitmap=reference.get(); 
    if(bitmap!=null) 

    returnbitmap; 


    else 

    /** 
    *加上一个对本地缓存的查找 
    */ 
    StringbitmapName=imageURL.substring(imageURL.lastIndexOf("/")+1); 
    FilecacheDir=newFile("/mnt/sdcard/test/"); 
    File[]cacheFiles=cacheDir.listFiles(); 
    inti=0; 
    if(null!=cacheFiles){ 
    for(;i<cacheFiles.length;i++) 

    if(bitmapName.equals(cacheFiles[i].getName())) 

    break; 


    if(i<cacheFiles.length) 

    returnBitmapFactory.decodeFile("/mnt/sdcard/test/"+bitmapName); 



    finalHandlerhandler=newHandler() 

    /*(non-Javadoc) 
    *@seeandroid.os.Handler#handleMessage(android.os.Message) 
    */ 
    @Override 
    publicvoidhandleMessage(Messagemsg) 

    //TODOAuto-generatedmethodstub 
    imageCallBack.imageLoad(imageView,(Bitmap)msg.obj); 

    }; 
    //如果不在内存缓存中,也不在本地(被jvm回收掉),则开启线程下载图片 
    newThread() 

    /*(non-Javadoc) 
    *@seejava.lang.Thread#run() 
    */ 
    @Override 
    publicvoidrun() 

    //TODOAuto-generatedmethodstub 
    InputStreambitmapIs=HttpUtils.getStreamFromURL(imageURL); 
    Bitmapbitmap=BitmapFactory.decodeStream(bitmapIs); 
    imageCache.put(imageURL,newSoftReference<Bitmap>(bitmap)); 
    Messagemsg=handler.obtainMessage(0,bitmap); 
    handler.sendMessage(msg); 
    Filedir=newFile("/mnt/sdcard/test/"); 
    if(!dir.exists()) 

    dir.mkdirs(); 

    FilebitmapFile=newFile("/mnt/sdcard/test/"+ 
    imageURL.substring(imageURL.lastIndexOf("/")+1)); 
    if(!bitmapFile.exists()) 

    try 

    bitmapFile.createNewFile(); 

    catch(IOExceptione) 

    //TODOAuto-generatedcatchblock 
    e.printStackTrace(); 


    FileOutputStreamfos; 
    try 

    fos=newFileOutputStream(bitmapFile); 
    bitmap.compress(Bitmap.CompressFormat.PNG, 
    100,fos); 
    fos.close(); 

    catch(FileNotFoundExceptione) 

    //TODOAuto-generatedcatchblock 
    e.printStackTrace(); 

    catch(IOExceptione) 

    //TODOAuto-generatedcatchblock 
    e.printStackTrace(); 


    }.start(); 
    returnnull; 

    publicinterfaceImageCallBack 

    publicvoidimageLoad(ImageViewimageView,Bitmapbitmap); 



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

    publicclassHttpUtils{ 
    publicstaticInputStreamgetStreamFromURL(StringimageURL){ 
    InputStreamin=null; 
    try{ 
    URLurl=newURL(imageURL); 
    HttpURLConnectionconnection=(HttpURLConnection)url.openConnection(); 
    in=connection.getInputStream(); 

    }catch(Exceptione){ 
    //TODOAuto-generatedcatchblock 
    e.printStackTrace(); 

    returnin; 




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

    publicclassImageCacheActivityextendsActivity{ 
    /**Calledwhentheactivityisfirstcreated.*/ 
    privateListViewlistview; 
    @Override 
    publicvoidonCreate(BundlesavedInstanceState){ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    listview=(ListView)findViewById(R.id.listView_list); 
    MyAdapteradapter=newMyAdapter(); 
    listview.setAdapter(adapter); 

    privateclassMyAdapterextendsBaseAdapter{ 
    privateAsyncBitmapLoaderasyncBitmapLoader; 
    publicMyAdapter(){ 
    asyncBitmapLoader=newAsyncBitmapLoader(); 

    @Override 
    publicintgetCount(){ 
    //TODOAuto-generatedmethodstub 
    return10; 

    @Override 
    publicObjectgetItem(intposition){ 
    //TODOAuto-generatedmethodstub 
    returnnull; 

    @Override 
    publiclonggetItemId(intposition){ 
    //TODOAuto-generatedmethodstub 
    return0; 

    @Override 
    publicViewgetView(intposition,ViewconvertView,ViewGroupparent){ 
    //TODOAuto-generatedmethodstub 
    if(convertView==null){ 
    convertView=LayoutInflater.from(getApplicationContext()).inflate(R.layout.list_item,null); 

    ImageViewimage=(ImageView)convertView.findViewById(R.id.addexam_list_icon); 
    StringimageURL="http://s.ata.net.cn/4f98db46908987a21a000003/logo/2012/04/114_80aaf295c083d07a496743699aac3193.png"; 
    Bitmapbitmap=asyncBitmapLoader.loadBitmap(image,imageURL,newImageCallBack(){ 

    @Override 
    publicvoidimageLoad(ImageViewimageView,Bitmapbitmap){ 
    //TODOAuto-generatedmethodstub 
    imageView.setImageBitmap(bitmap); 

    }); 
    if(bitmap==null) 

    image.setImageResource(R.drawable.ic_launcher); 

    else 

    image.setImageBitmap(bitmap); 


    returnconvertView; 





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

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

  • 相关阅读:
    Tomcat中 日志(控制台)中文乱码解决方法
    Maven 编译后 内存中中文数据乱码
    .gitignore无效,不能过滤某些文件
    允许远程用户登录访问mysql的方法
    针对MySQL创建用户后无法登录的原因
    解决Eclipse每次修改完代码后需要先Clean,不然部署不上文件的问题
    Struts2与JQurey ajax配合跨域请求
    Spring 定时任务之 @Scheduled cron表达式
    颜色是这样的,so,status bar和navigation bar颜色是一致的,
    尺寸,误差,
  • 原文地址:https://www.cnblogs.com/xieping/p/4784537.html
Copyright © 2011-2022 走看看