天天看點

一個好用的網絡圖檔下載下傳工具類ImageLoader (LruCache一級緩沖機制)



一級緩沖:也就是通常所說的記憶體緩沖,android采用LruCache實作      
二級緩沖:就是本地硬碟緩沖,android 采用DiskLruCache實作(等待下次學習,再分享)      
注:Android自帶的緩存類LruCache或LruDiskCache
      
package czg.czgnewsasyn;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.util.LruCache;
import android.widget.ImageView;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Created by Administrator on 2016/5/28.
 */
public class ImageLoader {
    private  ImageView mImageView;
    private String mUrl;

    //android使用緩沖 lru近期使用最少算法 第一個參數是鍵值對,第二個參數是類型
    private LruCache<String ,Bitmap> mCaches;  //第一個key參數就是url,第二個參數object就bitmap

    public ImageLoader() {
        //擷取最大可用記憶體
        int maxMemory= (int) Runtime.getRuntime().maxMemory();
        int cacheSize=maxMemory /4;
        mCaches=new LruCache<String ,Bitmap>(cacheSize){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                //在每次存入緩沖的時候調用
                //return super.sizeOf(key, value);
                return value.getByteCount();
            }
        };
    }

    //增加到緩沖
    public void addBitmapToCache(String url,Bitmap bitmap){
        if (getBitmapFromCache(url)==null){
            mCaches.put(url,bitmap);
        }

    }
    //從緩沖中擷取資料
    public Bitmap getBitmapFromCache(String url){
        return mCaches.get(url);
    }

    /**
     * 這個handler配合showImageByThread更新ImageView
     */
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //當image的Tag與我們的url相同所示,我們才去更新imageView,進而避免了緩沖的圖檔,對正确的圖檔産生的影響
            if (mImageView.getTag().equals(mUrl)){
                mImageView.setImageBitmap((Bitmap) msg.obj);

            }
        }
    };

    /**
     * 建立一個線程去解析url對于的Btimap圖檔對象,并把bitmap以消息的形式發送給主線程的Handler,并由handler設定給ImageView更新到主線程的UI上去
     * @param imageView
     * @param url
     */
    public void showImageByThread(ImageView imageView, final String url){
        mImageView = imageView;
        mUrl=url;
        new Thread(){
            @Override
            public void run() {
                super.run();
                Bitmap bitmap = getBitmapFromURL(url);
                //通過message傳遞bitmap給handler,,通知handler去更新ImageView對象
                Message message = Message.obtain();
                message.obj = bitmap;
                mHandler.sendMessage(message);

            }
        }.start();

    }

    /**
     * 通過圖檔的url位址解析為Bitmap對象
     * @param urlString
     * @return
     */
    public Bitmap getBitmapFromURL(String urlString){
        Bitmap bitmap;
        InputStream is=null;
        try {
            URL url = new URL(urlString);
            HttpURLConnection  connection = (HttpURLConnection) url.openConnection();
            is = new BufferedInputStream(connection.getInputStream());
            bitmap = BitmapFactory.decodeStream(is);
            connection.disconnect();

//            try {
//                Thread.sleep(1000);  //模拟網絡不好的情況
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
            return bitmap;

        } catch (IOException e) {
            e.printStackTrace();
        }finally {

            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return  null;
    }

    public void showImageByAsyncTask(ImageView imageView,String url){
        //檢查緩沖中是否有這張圖檔,如果有則直接從緩沖中擷取圖檔,否則,啟用異步下載下傳圖檔
        Bitmap bitmap = getBitmapFromCache(url);
        if (bitmap==null){
            new NewsAsyncTask(imageView,url).execute(url);
        }else {
            imageView.setImageBitmap(bitmap);
        }

    }
    //第一個參數是Url,中間過程不需要則采用Void,最後傳回是一個Bitmap
    private class NewsAsyncTask extends AsyncTask<String,Void,Bitmap>{
        private ImageView mImageView;
        private String mUrl;

        public NewsAsyncTask(ImageView imageView,String url) {
            this.mImageView = imageView;
            this.mUrl=url;
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            String url = params[0];
            //從網絡擷取圖檔
            Bitmap bitmap = getBitmapFromURL(url);
            if (bitmap!=null){
                //将不在緩沖中的圖檔,加入緩沖
                addBitmapToCache(url,bitmap);
            }
            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            if (mImageView.getTag().equals(mUrl)){
                mImageView.setImageBitmap(bitmap);
            }
        }
    }
}
      

繼續閱讀