您的位置:首页 > 移动开发 > Android开发

android之图片异步加载并缓存到本地

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

 

[html]
view plain
copy

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卡,如果内存中没有,则从本地查找,如果本地没有则从网络获取图片。

[html]
view plain
copy

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;  
          
    }  
}  

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

[html]
view plain
copy

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



这是一种很实用的方法,大家自己试试吧!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: