异步下载图片和图片缓存

功能如下:

异步下载图片和图片缓存_第1张图片

流程如下:

异步下载图片和图片缓存_第2张图片

   RemoteImageViewActivity:

    public class RemoteImageViewActivity extends Activity {  
        /** Called when the activity is first created. */  
        @Override  
        public void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.main);  
      
            RemoteImageView img = (RemoteImageView) findViewById(R.id.remote_img);  
            img.setDefaultImage(R.drawable.ic_launcher);  
            img.setImageUrl("http://img2.kwcdn.kuwo.cn:81/star/albumcover/120/7/8/83787_1323997225.jpg");  
        }  
      
        @Override  
        protected void onPause() {  
            // TODO Auto-generated method stub  
            super.onPause();  
        }  
    }  

  ImageCache:

    public class ImageCache extends WeakHashMap{  
      
        /** 
         * 判断该url是否存在 
         * @param url 
         * @return 
         */  
        public boolean isCached(String url){  
            return containsKey(url) && get(url) != null;  
        }  
    }  

   RemoteImageApplication:

    public class RemoteImageApplication extends Application {  
      
        public static final String TAG = "RemoteImageApplication";  
      
        private static RemoteImageApplication application;  
      
        private ImageCache mImageCache;  
      
        public SharedPreferences prefs = null;  
      
          
        public static RemoteImageApplication getInstance() {  
            return application;  
        }  
      
        @Override  
        public void onCreate() {  
            // TODO Auto-generated method stub  
            super.onCreate();  
      
            application = this;  
      
            mImageCache = new ImageCache();  
      
            prefs = PreferenceManager.getDefaultSharedPreferences(this);  
        }  
      
        public ImageCache getImageCache() {  
            return mImageCache;  
        }  
    }  

RemoteSettings:

    public class RemoteSettings {  
      
        public static final String CACHE_SIZE = "cache_size";  //图片缓存保留大小,如果超过该大小,即进行自动清除缓存.  
      
    }  

RemoteImageView:

    public class RemoteImageView extends ImageView {  
      
        private Context mContext;  
      
        private static int mCacheSize = 150; // 设置的缓存大小。  
      
        private static final int MAX_FAILURES = 3; // 下载的尝试请求次数  
      
        private int mFailure; // 下载失败次数  
      
        private String mUrl; // 当前下载的url  
      
        private String mCurrentlyGrabbedUrl; // 当前下载成功的url  
      
        private final static String JAMENDO_DIR = "Android/data/com.teleca.jamendo"; // 文件缓存存放的路径.  
      
        private final static long MB = 1073741824;  
      
        public RemoteImageView(Context context, AttributeSet attrs, int defStyle) {  
            super(context, attrs, defStyle);  
            mContext = context;  
        }  
      
        public RemoteImageView(Context context, AttributeSet attrs) {  
            super(context, attrs);  
            mContext = context;  
        }  
      
        public RemoteImageView(Context context) {  
            super(context);  
            mContext = context;  
        }  
      
        /** 
         * 设置默认图片 
         */  
        public void setDefaultImage(Integer resid) {  
            setImageResource(resid);  
        }  
      
        /** 
         * 设置需要异步加载的图片 
         */  
        public void setImageUrl(String url) {  
      
            // 下载失败进行重试,如果重试次数超过规定的限制,则直接返回.  
            if (mUrl != null  
                    && mUrl.equals(url)  
                    && (mCurrentlyGrabbedUrl == null || (mCurrentlyGrabbedUrl != null && !mCurrentlyGrabbedUrl  
                            .equals(url)))) {  
                mFailure++;  
                if (mFailure > MAX_FAILURES) {  
                    Log.e(RemoteImageApplication.TAG, "下载该图片地址失败:" + url);  
                    return;  
                }  
            } else {  
      
                mUrl = url;  
                mFailure = 0;  
            }  
      
            ImageCache imageCache = RemoteImageApplication.getInstance()  
                    .getImageCache();  
      
            if (imageCache.isCached(url)) {  
                setImageBitmap(imageCache.get(url));  
            } else {  
                // 如果内存中没有该缓存,则从文件中进行查找.  
                String fileName = convertUrlToFileName(url); // 进行文件名处理  
      
                String filepath = getDirectory(fileName); // 取得缓存文件夹目录  
      
                String pathFileName = filepath + "/" + fileName; // 组拼文件  
      
                File pathFile = new File(pathFileName);  
                if (!pathFile.exists()) {  
                    try {  
                        pathFile.createNewFile();  
                    } catch (IOException e) {  
                        Log.d(RemoteImageApplication.TAG, "创建图片文件失败:"  
                                + pathFileName);  
                    }  
                }  
      
                Bitmap tbmp = BitmapFactory.decodeFile(pathFileName);  
      
                if (tbmp == null) {  
                    Log.d(RemoteImageApplication.TAG, "图片文件不存在,开始进行下载");  
                    try {  
                        new DownloadTask().execute(url);  
                    } catch (RejectedExecutionException e) {  
                        Log.d(RemoteImageApplication.TAG, "下载失败");  
                    }  
                } else {  
                    Log.i(RemoteImageApplication.TAG, "从文件中加载图片");  
                    RemoteImageApplication.getInstance().getImageCache()  
                            .put(url, tbmp);  
                    this.setImageBitmap(tbmp);  
                }  
      
                updateCacheSize(pathFileName); // 进行检测文件大小,以便于清除缓存.  
      
            }  
      
        }  
      
        private void updateCacheSize(String pathFileName) {  
            // TODO Auto-generated method stub  
            updateSizeCache(pathFileName);  
      
        }  
      
        /** 
         * 检查文件目录是否超过规定的缓存大小 
         *  
         * @param fileName 
         */  
        private void updateSizeCache(String pathFileName) {  
            // TODO Auto-generated method stub  
            mCacheSize = PreferenceManager.getDefaultSharedPreferences(mContext)  
                    .getInt(RemoteSettings.CACHE_SIZE, 100); // 读取设置的缓存大小,前台可以动态设置此值  
      
            if (isSDCardEnable()) {  
                String extStorageDirectory = Environment  
                        .getExternalStorageDirectory().toString(); // 取得SD根路径  
      
                String dirPath = extStorageDirectory + "/" + JAMENDO_DIR  
                        + "/imagecache";  
      
                File dirFile = new File(dirPath);  
      
                File[] files = dirFile.listFiles();  
      
                long dirSize = 0;  
      
                for (File file : files) {  
      
                    dirSize += file.length();  
                }  
      
                if (dirSize > mCacheSize * MB) {  
                    clearCache();  
                }  
            }  
      
        }  
      
        /** 
         * 异步下载图片 
         *  
         * @ClassName: DownloadTask 
         * @author 姜涛 
         * @version 1.0 2012-1-15 下午5:06:21 
         */  
        class DownloadTask extends AsyncTask {  
      
            private String mTaskUrl;  
            private Bitmap mBmp = null;  
      
            @Override  
            public void onPreExecute() {  
                // loadDefaultImage();  
                super.onPreExecute();  
            }  
      
            @Override  
            public String doInBackground(String... params) {  
      
                mTaskUrl = params[0];  
                InputStream stream = null;  
                URL imageUrl;  
                Bitmap bmp = null;  
      
                try {  
                    imageUrl = new URL(mTaskUrl);  
                    try {  
                        stream = imageUrl.openStream();  
                        bmp = BitmapFactory.decodeStream(stream);  
                        try {  
                            if (bmp != null) {  
                                mBmp = bmp;  
                                RemoteImageApplication.getInstance()  
                                        .getImageCache().put(mTaskUrl, bmp);  
                                Log.d(RemoteImageApplication.TAG,  
                                        "图片缓存到application中: " + mTaskUrl);  
      
                            }  
                        } catch (NullPointerException e) {  
                            Log.w(RemoteImageApplication.TAG, "下载失败,图片为空:"  
                                    + mTaskUrl);  
                        }  
                    } catch (IOException e) {  
                        Log.w(RemoteImageApplication.TAG, "无法加载该url:" + mTaskUrl);  
                    } finally {  
                        try {  
                            if (stream != null) {  
                                stream.close();  
                            }  
                        } catch (IOException e) {  
                        }  
                    }  
      
                } catch (MalformedURLException e) {  
                    e.printStackTrace();  
                }  
                return mTaskUrl;  
            }  
      
            @Override  
            public void onPostExecute(String url) {  
                super.onPostExecute(url);  
      
                Bitmap bmp = RemoteImageApplication.getInstance().getImageCache()  
                        .get(url);  
                if (bmp == null) {  
                    Log.w(RemoteImageApplication.TAG, "尝试重新下载:" + url);  
                    RemoteImageView.this.setImageUrl(url);  
                } else {  
      
                    RemoteImageView.this.setImageBitmap(bmp);  
                    mCurrentlyGrabbedUrl = url;  
                    saveBmpToSd(mBmp, url);  
      
                }  
            }  
      
        };  
      
        /** 
         * 把图片保存到本地 
         *  
         * @param bm 
         * @param url 
         */  
        private void saveBmpToSd(Bitmap bm, String url) {  
      
            if (bm == null) {  
                return;  
            }  
      
            if (mCacheSize == 0) {  
                return;  
            }  
      
            String filename = convertUrlToFileName(url);  
            String dir = getDirectory(filename);  
            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();  
      
                Log.i(RemoteImageApplication.TAG, "图片已保存到sd卡");  
      
            } catch (FileNotFoundException e) {  
                Log.w(RemoteImageApplication.TAG, "无法找到文件目录");  
      
            } catch (IOException e) {  
                Log.w(RemoteImageApplication.TAG, "操作文件出错");  
            }  
      
        }  
      
        /** 
         * 组拼文件名,后缀名用dat代替,避免别人使用图片管理器搜索出这种对于她们无用的图片. 
         *  
         * @param url 
         * @return 
         */  
        private String convertUrlToFileName(String url) {  
            String filename = url;  
            filename = filename.replace("http://", "");  
            filename = filename.replace("/", ".");  
            filename = filename.replace(":", ".");  
            filename = filename.replace("jpg", "dat");  
            filename = filename.replace("png", "dat");  
            return filename;  
        }  
      
        /** 
         * 返回缓存图片所存放的文件夹 
         *  
         * @param filename 
         * @return 
         */  
        private String getDirectory(String filename) {  
      
            String extStorageDirectory = Environment.getExternalStorageDirectory()  
                    .toString(); // 取得SD根路径  
      
            String dirPath = extStorageDirectory + "/" + JAMENDO_DIR  
                    + "/imagecache";  
      
            File dirFile = new File(dirPath);  
      
            if (!dirFile.exists()) {  
                dirFile.mkdirs();  
            }  
      
            return dirPath;  
      
        }  
      
        /** 
         * 清除缓存 
         */  
        private void clearCache() {  
      
            if (isSDCardEnable()) {  
                String extStorageDirectory = Environment  
                        .getExternalStorageDirectory().toString(); // 取得SD根路径  
      
                String dirPath = extStorageDirectory + "/" + JAMENDO_DIR  
                        + "/imagecache";  
      
                File dir = new File(dirPath);  
      
                File[] files = dir.listFiles(); // 取得该目录下的所有文件  
      
                if (files == null || files.length == 0) {  
                    return;  
                }  
      
                for (File file : files) {  
                    file.delete();  
                }  
      
                Log.d(RemoteImageApplication.TAG, "已清除缓存:" + dirPath);  
            }  
        }  
      
        /** 
         * 判断SD卡是否可用 
         */  
        public static boolean isSDCardEnable() {  
      
            return Environment.getExternalStorageState().equals(  
                    Environment.MEDIA_MOUNTED);  
        }  
      
    }  

本文转自:http://lewisliu.iteye.com/blog/1346820

你可能感兴趣的:(Android应用层)