zoukankan      html  css  js  c++  java
  • android 图片异步下载 缓存处理 自定义ImageView

     2)BitmapCache.java,  好久没有过来博客园了,今天项目里面使用到了图片传输,后来便自己琢磨了一下,最后通过查阅相关资料,做了一个自定义imageview,其可以实现只要传输给其图片路径,

    其它的事就全部交给它处理了,不用再去管什么自己写handler+message,或者使用异步的类.使用起来也非常简单。当然希望有朋友有更好一些的改进,欢迎交流。

    现在我就来介绍一下这个自定义的imageview,它主要使用要的文件有如下的几个:

    1)AsyImageLoad.java    2)BitmapCache.java,   3)ImageFileCache.java,  4)ImageGetFromHttp.java

    5)回调接口
        public interface doCallback
        {
        /**
        * 回调传输下载 下来后的值
        * @param bitmap
        */
        void doPostBack(Bitmap bitmap);
        }

     7)自定义的ImageView --->myImageView

     1)AsyImageLoad.java  

    package com.yitu.Util;

    import java.io.FilterInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.HttpStatus;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.AsyncTask;
    import android.util.Log;
    import com.df.dianping.R;
    import com.yitu.Util.ImageGetFromHttp.FlushedInputStream;
    import com.yitu.Util.ImageGetFromHttp.doCallback;
    /**
     * 自定义异步任务
     */
    public class AnsyImageLoad extends AsyncTask<String,Void, Bitmap>
    {
    private static final String LOG_TAG = "AnsyImageLoad";
    doCallback doback;
    String url="";
    Context mycontext;
    public AnsyImageLoad(String url, doCallback doback2,Context context) {
    // TODO Auto-generated constructor stub
    this.url=url;
    this.doback=doback2;
    this.mycontext=context;
    }
    @Override
    protected void onCancelled() {
    // TODO Auto-generated method stub
    super.onCancelled();
    }
    @Override
    protected void onPostExecute(Bitmap result) {
    // TODO Auto-generated method stub
    super.onPostExecute(result);
       this.doback.doPostBack(result); //doback(result);
       Log.i("net", "执行任务回调--->取到一个远程数据");
    }
    @Override
    protected void onPreExecute() {
    // TODO Auto-generated method stub
    super.onPreExecute();
    //拿到一个默认图片
    Log.i("net", "初始化执行任务--->取到一个本地数据");
    this.doback.doPostBack(null);
    }
    @Override
    protected Bitmap doInBackground(String... arg0) {
    // TODO Auto-generated method stub
    if(url.equals(""))
    {
    //返回默认图标icon
    //返回默认图片
    this.doback.doPostBack(BitmapFactory.decodeResource(mycontext.getResources(), R.drawable.icon));
    }
    else
    {
           final HttpClient client = new DefaultHttpClient();
           final HttpGet getRequest = new HttpGet(arg0[0]);  
    try
    {
       
           HttpResponse response = client.execute(getRequest);
               final int statusCode = response.getStatusLine().getStatusCode();
               if (statusCode != HttpStatus.SC_OK) {
                   Log.i("image_load", "Error " + statusCode + " while retrieving bitmap from " + url);
                   return null;
               }
               final HttpEntity entity = response.getEntity();
               if (entity != null) {
                   InputStream inputStream = null;
                   try {
                       inputStream = entity.getContent();
                       FilterInputStream fit = new FlushedInputStream(inputStream);
                       Log.i("net", "执行任务完毕--->取到一个远程数据--->"+arg0[0]);
                       return BitmapFactory.decodeStream(fit);
                   } finally {
                       if (inputStream != null) {
                           inputStream.close();
                           inputStream = null;
                       }
                       entity.consumeContent();
                   }
               }
    }
            catch (IOException e) {
                getRequest.abort();
                Log.w("net", "I/O error while retrieving bitmap from " + url, e);
            } catch (IllegalStateException e) {
                getRequest.abort();
                Log.w("net", "Incorrect URL: " + url);
            } catch (Exception e) {
                getRequest.abort();
                Log.w("net", "Error while retrieving bitmap from " + url, e);
            } finally {
                client.getConnectionManager().shutdown();
            }
    //this.doPostBack(bitmap)
    //返回真实图片
    }
    //return BitmapFactory.decodeResource(mycontext.getResources(), R.drawable.icon);
    return null;
    }
    }

     2)BitmapCache.java, 

     package com.yitu.Util;


    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.util.Log;

    import com.df.dianping.R;
    import com.yitu.Util.ImageGetFromHttp.doCallback;

    /**
     * @author wsf
     * 2013-8-13 20:45
     * 用于缓存Bitmap
     * 使用方法
     * 
     */
    public class BitmapCache implements doCallback {
    public Context mycontext;
    public ImageMemoryCache memoryCache=null;
    public ImageGetFromHttp fromhttp=null;
    public ImageFileCache fileCache=null;
    Bitmap result;
    /*** 获得一张图片,从三个地方获取,首先是内存缓存,然后是文件缓存,最后从网络获取 ***/
    public void setBitmap(final String url,Context context,final doCallback docallback) {
    this.mycontext=context;
    InitCatch(context);
       // 从内存缓存中获取图片
       result = memoryCache.getBitmapFromCache(url);
       if (result == null) {
           // 文件缓存中获取
           result = fileCache.getImage(url);
           if (result == null) {
            /**
            * 此处为wsf添加代码 
            */        
            AnsyImageLoad imageload=new AnsyImageLoad(url,
            new doCallback() {
    @Override
    public void doPostBack(Bitmap bitmap) {
    // TODO Auto-generated method stub
    Log.i("net", "被执行了一次--->docallback");
    result=bitmap;
    if(bitmap!=null)
    {
                   fileCache.saveBitmap(result, url);
                   memoryCache.addBitmapToCache(url, result);
                   docallback.doPostBack(bitmap);
    }
    else
    {
    docallback.doPostBack(BitmapFactory.decodeResource(mycontext.getResources(), R.drawable.icon));
    }
    }
    },context);
            imageload.execute(url);
            /**
            * 以上为wsf添加代码 
            */
           } else {
               // 添加到内存缓存
               memoryCache.addBitmapToCache(url, result);
           }
       }
       docallback.doPostBack(result);
    }
    /**
    * 初始化数据
    * @param context
    */
    public void InitCatch(Context context)
    {
    memoryCache=new ImageMemoryCache(context);
    fromhttp=new ImageGetFromHttp();
    fileCache=new ImageFileCache();
    }
    /**
    * 执行结束时回调方法
    */
    @Override
    public void doPostBack(Bitmap bitmap) {
    // TODO Auto-generated method stub
    }

        /** 将url转成文件名 **/
        private String convertUrlToFileName(String url) {
            String[] strs = url.split("/");
            return strs[strs.length - 1] + ".cach";
        }
    }

     3)ImageFileCache.java,

     package com.yitu.Util;


    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.util.Arrays;
    import java.util.Comparator;

    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.Environment;
    import android.os.StatFs;
    import android.util.Log;
    /**
     * http://keegan-lee.diandian.com/post/2012-12-06/40047548955
     * @author wsf
     *
     */
    public class ImageFileCache {

        private static final String CACHDIR = "ImgCach";
        private static final String WHOLESALE_CONV = ".cach";
                                                                
        private static final int MB = 1024*1024;
        private static final int CACHE_SIZE = 10;
        private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 10;
                                                                    
        public ImageFileCache() {
            //清理文件缓存
            removeCache(getDirectory());
        }
                                                                    
        /** 从缓存中获取图片 **/
        public Bitmap getImage(final String url) {    
            final String path = getDirectory() + "/" + convertUrlToFileName(url);
            File file = new File(path);
            if (file.exists()) {
                Bitmap bmp = BitmapFactory.decodeFile(path);
                if (bmp == null) {
                    file.delete();
                } else {
                    updateFileTime(path);
                    return bmp;
                }
            }
            return null;
        }
                                                                    
        /** 将图片存入文件缓存 **/
        public void saveBitmap(Bitmap bm, String url) {
            if (bm == null) {
                return;
            }
            //判断sdcard上的空间
            if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
                //SD空间不足
                return;
            }
            String filename = convertUrlToFileName(url);
            String dir = getDirectory();
            File dirFile = new File(dir);
            if (!dirFile.exists())
                dirFile.mkdirs();
            File file = new File(dir +"/" + filename);
            try {
                file.createNewFile();
                OutputStream outStream = new FileOutputStream(file);
                bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
                outStream.flush();
                outStream.close();
            } catch (FileNotFoundException e) {
                Log.w("ImageFileCache", "FileNotFoundException");
            } catch (IOException e) {
                Log.w("ImageFileCache", "IOException");
            }
        } 
                                                                    
        /**
         * 计算存储目录下的文件大小,
         * 当文件总大小大于规定的CACHE_SIZE或者sdcard剩余空间小于FREE_SD_SPACE_NEEDED_TO_CACHE的规定
         * 那么删除40%最近没有被使用的文件
         */
        private boolean removeCache(String dirPath) {
            File dir = new File(dirPath);
            File[] files = dir.listFiles();
            if (files == null) {
                return true;
            }
            if (!android.os.Environment.getExternalStorageState().equals(
                    android.os.Environment.MEDIA_MOUNTED)) {
                return false;
            }
                                                                
            int dirSize = 0;
            for (int i = 0; i < files.length; i++) {
                if (files[i].getName().contains(WHOLESALE_CONV)) {
                    dirSize += files[i].length();
                }
            }
                                                                
            if (dirSize > CACHE_SIZE * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
                int removeFactor = (int) ((0.4 * files.length) + 1);
                Arrays.sort(files, new FileLastModifSort());
                for (int i = 0; i < removeFactor; i++) {
                    if (files[i].getName().contains(WHOLESALE_CONV)) {
                        files[i].delete();
                    }
                }
            }
                                                                
            if (freeSpaceOnSd() <= CACHE_SIZE) {
                return false;
            }
                                                                        
            return true;
        }
                                                                    
        /** 修改文件的最后修改时间 **/
        public void updateFileTime(String path) {
            File file = new File(path);
            long newModifiedTime = System.currentTimeMillis();
            file.setLastModified(newModifiedTime);
        }
                                                                    
        /** 计算sdcard上的剩余空间 **/
        private int freeSpaceOnSd() {
            StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
            double sdFreeMB = ((double)stat.getAvailableBlocks() * (double) stat.getBlockSize()) / MB;
            return (int) sdFreeMB;
        } 
                                                                    
        /** 将url转成文件名 **/
        private String convertUrlToFileName(String url) {
            String[] strs = url.split("/");
            return strs[strs.length - 1] + WHOLESALE_CONV;
        }
                                                                    
        /** 获得缓存目录 **/
        private String getDirectory() {
            String dir = getSDPath() + "/" + CACHDIR;
            return dir;
        }
                                                                    
        /** 取SD卡路径 **/
        private String getSDPath() {
            File sdDir = null;
            boolean sdCardExist = Environment.getExternalStorageState().equals(
                    android.os.Environment.MEDIA_MOUNTED);  //判断sd卡是否存在
            if (sdCardExist) {
                sdDir = Environment.getExternalStorageDirectory();  //获取根目录
            }
            if (sdDir != null) {
                return sdDir.toString();
            } else {
                return "";
            }
        } 
                                                                
        /**
         * 根据文件的最后修改时间进行排序
         */
        private class FileLastModifSort implements Comparator<File> {
            public int compare(File arg0, File arg1) {
                if (arg0.lastModified() > arg1.lastModified()) {
                    return 1;
                } else if (arg0.lastModified() == arg1.lastModified()) {
                    return 0;
                } else {
                    return -1;
                }
            }
        }
    }

     4)ImageGetFromHttp.java

      
    package com.yitu.Util;
    import java.io.FilterInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.util.Log;
    /**
     * http://keegan-lee.diandian.com/post/2012-12-06/40047548955
     * @author wsf
     *
     */
    public class ImageGetFromHttp {
    private  Bitmap result=null;                            
        private static final String LOG_TAG = "ImageGetFromHttp";    
        public  Bitmap downloadBitmap(String url,Context context) 
        {
            /**
            * 此处为wsf添加代码 
            */
           
            AnsyImageLoad imageload=new AnsyImageLoad(url,
            new doCallback() {
    @Override
    public void doPostBack(Bitmap bitmap) {
    // TODO Auto-generated method stub
    Log.i("net", "被执行了一次--->docallback");
    result = bitmap;
    }
    },context);
            imageload.execute(url);
            /**
            * 以上为wsf添加代码 
            */
            return result;
        }
                                                           
        /*
         * An InputStream that skips the exact number of bytes provided, unless it reaches EOF.
         */
        static class FlushedInputStream extends FilterInputStream {
            public FlushedInputStream(InputStream inputStream) {
                super(inputStream);
            }
                                                           
            @Override
            public long skip(long n) throws IOException {
                long totalBytesSkipped = 0L;
                while (totalBytesSkipped < n) {
                    long bytesSkipped = in.skip(n - totalBytesSkipped);
                    if (bytesSkipped == 0L) {
                        int b = read();
                        if (b < 0) {
                            break;  // we reached EOF
                        } else {
                            bytesSkipped = 1; // we read one byte
                        }
                    }
                    totalBytesSkipped += bytesSkipped;
                }
                return totalBytesSkipped;
            }
        }
        public interface doCallback
        {
        /**
        * 回调传输下载 下来后的值
        * @param bitmap
        */
        void doPostBack(Bitmap bitmap);
        }
        
    }


    6)自定义的控件 myImageView

    package com.df.widget;//com.df.widget.myImageView
    import com.yitu.Util.BitmapCache;
    import com.yitu.Util.ImageGetFromHttp.doCallback;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.drawable.BitmapDrawable;
    import android.util.AttributeSet;
    import android.widget.ImageView;
    /**
     * 自定义图像显示控件
     * (所使用到的类有三个,AsyImageLoad.java,BitmapCache.java,ImageFileCache.java,ImageGetFromHttp.java
     * ImageMemoryCache.java)
     * @author wsf
     *
     */
    public class myImageView extends ImageView {
    private Context mycontext;
    public myImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    // TODO Auto-generated constructor stub
    this.mycontext=context;
    }
    public myImageView(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
    this.mycontext=context;
    }
    public myImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
    this.mycontext=context;
    }
    /**
    * 采集远程的网络数据
    * @param url
    */
    public void setImage(String url)
    {
    BitmapCache bitcatch=new BitmapCache();
    bitcatch.setBitmap(url, 
    mycontext,new doCallback() {
    public void doPostBack(Bitmap bitmap) {
    // TODO Auto-generated method stub
    BitmapDrawable drawable=new BitmapDrawable(bitmap);
    myImageView.this.setBackgroundDrawable(drawable);
    }
    });
    }
    /**
    * 根所本地的资源来设定图片的背景资源
    * @param resid
    */
    public void setImage(int resid)
    {
    this.setBackgroundResource(resid);
    }
    }

    7)调用示例

      /**使用自定义的图片显示控件*/

    myimageview=(myImageView)findViewById(R.id.my_view);
    myimageview.setImage("http://d.hiphotos.baidu.com/album/w%3D2048/sign=79c90f23728da9774e2f812b8469f919/8b13632762d0f703a2d659cc09fa513d2697c5be.jpg");
    /**使用自定义的图片显示控件*/

     8)layout.中的布局文件

         <com.df.widget.myImageView 

            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/my_view"        
            />

     

     

    9)最后效果

     

        

     

  • 相关阅读:
    雷霆战机
    各种 Python 库/模块/工具
    redis
    25
    为什么Python中“2==2>1”结果为True
    thinkphp3.2路由美化,url简化
    thinkphp调整框架核心目录think的位置
    thinkphp3.2中开启静态缓存后对404页面的处理方法
    thinphp中volist嵌套循环时变量$i 被污染问题,key="k"
    thinkphp中如何是实现多表查询
  • 原文地址:https://www.cnblogs.com/wsfjlagr/p/3257639.html
Copyright © 2011-2022 走看看