溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android 實現異步加載圖片

發布時間:2020-05-16 07:06:30 來源:網絡 閱讀:339 作者:鄒君安 欄目:移動開發

麥洛開通博客以來,有一段時間沒有更新博文了.主要是麥洛這段時間因項目開發實在太忙了.今天周六還在公司加班,苦逼程序猿都是這樣生活的.

今天在做項目的時候,有一個實現異步加載圖片的功能,雖然比較簡單但還是記錄一下吧.因為麥洛之前實現異步加載圖片都是使用了AsynTask這個API,繼續這個類,實現起來非常簡單也很方便.在doInBackground()方法里實現下載邏輯.具體實現如下

實現邏輯是:先從內存中讀取,如果內存中有這張圖片,則直接使用;如果內存沒有再到sdcard上讀取,如果有則顯示;如果sdcard上還沒有則到網絡上讀取.內存中開啟緩存是參考了網上的實現.麥洛在這里非常感謝喜歡分享的程序猿們.

Android 實現異步加載圖片

public class ImageDownloader extends AsyncTask<String, Integer, Object> {    private static final String TAG = "ImageDownloader";    // 為了加快速度,在內存中開啟緩存(主要應用于重復圖片較多時,或者同一個圖片要多次被訪問,比如在ListView時來回滾動)
    private Map<String, SoftReference<Drawable>> p_w_picpathCache = new HashMap<String, SoftReference<Drawable>>();    /**
     * 顯示圖片的控件     */
    private ImageView mImageView;    public ImageDownloader(ImageView p_w_picpath) {
        mImageView = p_w_picpath;
    }

    @Override    protected void onPreExecute() {        super.onPreExecute();
    }

    @Override    protected Object doInBackground(String... params) {        // Log.i("ImageDownloader", "loading p_w_picpath...");
        String url = params[0];
        Drawable drawable = null;        try {            if (!"".equals(url) && url != null) {
                String fileName = url.hashCode()+".jpg";                // 如果緩存過就從緩存中取出數據
                if (p_w_picpathCache.containsKey(fileName)) {
                    SoftReference<Drawable> softReference = p_w_picpathCache.get(fileName);
                    drawable = softReference.get();                    if (drawable != null) {                        return drawable;
                    }
                }
                File dir = new File(FileConstant.IMAGE_FILE_PATH);                if (!dir.exists()) {                    boolean m = dir.mkdirs();
                }
                File file = new File(dir, fileName);                if (file.exists() && file.length() > 0) {
                    Log.i(TAG, "load p_w_picpath from sd card");                    // 如果文件存在則直接讀取sdcard
                    drawable = readFromSdcard(file);
                } else {                    //file.createNewFile();
                    Log.i(TAG, "load p_w_picpath from network");
                    URL p_w_picpathUrl = new URL(url);                    // 寫入sdcard
                    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                        saveImageFile(p_w_picpathUrl, file);
                        drawable = Drawable.createFromStream(new FileInputStream(file), fileName);
                    }else{                        //直接從流讀取
                        drawable = Drawable.createFromStream(p_w_picpathUrl.openStream(), fileName);
                    }
                }                if(drawable!=null){                    //保存在緩存中
                    p_w_picpathCache.put(fileName, new SoftReference<Drawable>(drawable));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } 
        return drawable;
    }    /**
     * save p_w_picpath*/
    private void saveImageFile(URL url, File file) {
        FileOutputStream out = null;
        InputStream in = null;        try {
            file.deleteOnExit();
            out = new FileOutputStream(file);
            in = url.openStream();            byte[] buf = new byte[1024];            int len = -1;            while((len = in.read(buf))!=-1){
                out.write(buf, 0, len);
                out.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {            if(out!=null){                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }            if(in!=null){                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }    /**
     * 從sdcard中獲取圖片*/
    private Drawable readFromSdcard(File file) throws Exception {
        FileInputStream in = new FileInputStream(file);        return Drawable.createFromStream(in, file.getName());
    }

    @Override    protected void onPostExecute(Object result) {        super.onPostExecute(result);
        Drawable drawable = (Drawable) result;        if (mImageView != null && drawable != null) {
            mImageView.setBackgroundDrawable(drawable);
        }
    }

    @Override    protected void onProgressUpdate(Integer... values) {        super.onProgressUpdate(values);
    }

    @Override    protected void onCancelled() {        super.onCancelled();
    }

}

Android 實現異步加載圖片

使用時:

ImageDownloader loader = new ImageDownloader(p_w_picpathView);
loader.execute(url);

其實這樣的話,還有一些隱患的,就是說這個類實現還是有些問題的.比如每次都在p_w_picpathView中設置網絡上的圖片時,其實是沒有使用到這個類里面的內存緩存的,就是p_w_picpathCache

Map<String, SoftReference<Drawable>> p_w_picpathCache = new HashMap<String, SoftReference<Drawable>>();

因為每次設置p_w_picpathView的時候,都是new了一個ImageDownloader的對象.所以每個ImageDownloader對象里面都是獨立的一個p_w_picpathCache.

      另外,AsynTask也是一個線程.而每次使用都開一個線程來load 圖片,對線程個數沒有進行顯示,畢竟線程數目還是有限制的.

所以麥洛今天發現了這個問題,于是參考了別人的實現,使用了線程池,實現邏輯也上面的代碼一樣,先從內存讀取,如果沒有到sdcard讀取,如果還是沒有,則是網絡讀取;實現沒有使用AsynTask,具體代碼如下:

Android 實現異步加載圖片

/**
 * 異步加載圖片,并將圖片設置到ImageView控件中*/public class ImageDownloader extends AsyncTask<String, Integer, Object> {    private static final String TAG = "ImageDownloader";    // 為了加快速度,在內存中開啟緩存(主要應用于重復圖片較多時,或者同一個圖片要多次被訪問,比如在ListView時來回滾動)
    private Map<String, SoftReference<Drawable>> p_w_picpathCache = new HashMap<String, SoftReference<Drawable>>();    /**
     * 顯示圖片的控件     */
    private ImageView mImageView;    public ImageDownloader(ImageView p_w_picpath) {
        mImageView = p_w_picpath;
    }

    @Override    protected void onPreExecute() {        super.onPreExecute();
    }

    @Override    protected Object doInBackground(String... params) {        // Log.i("ImageDownloader", "loading p_w_picpath...");
        String url = params[0];
        Drawable drawable = null;        try {            if (!"".equals(url) && url != null) {
                String fileName = url.hashCode()+".jpg";                // 如果緩存過就從緩存中取出數據
                if (p_w_picpathCache.containsKey(fileName)) {
                    SoftReference<Drawable> softReference = p_w_picpathCache.get(fileName);
                    drawable = softReference.get();                    if (drawable != null) {                        return drawable;
                    }
                }
                File dir = new File(FileConstant.IMAGE_FILE_PATH);                if (!dir.exists()) {                    boolean m = dir.mkdirs();
                }
                File file = new File(dir, fileName);                if (file.exists() && file.length() > 0) {
                    Log.i(TAG, "load p_w_picpath from sd card");                    // 如果文件存在則直接讀取sdcard
                    drawable = readFromSdcard(file);
                } else {                    //file.createNewFile();
                    Log.i(TAG, "load p_w_picpath from network");
                    URL p_w_picpathUrl = new URL(url);                    // 寫入sdcard
                    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                        saveImageFile(p_w_picpathUrl, file);
                        drawable = Drawable.createFromStream(new FileInputStream(file), fileName);
                    }else{                        //直接從流讀取
                        drawable = Drawable.createFromStream(p_w_picpathUrl.openStream(), fileName);
                    }
                }                if(drawable!=null){                    //保存在緩存中
                    p_w_picpathCache.put(fileName, new SoftReference<Drawable>(drawable));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } 
        return drawable;
    }    /**
     * save p_w_picpath*/
    private void saveImageFile(URL url, File file) {
        FileOutputStream out = null;
        InputStream in = null;        try {
            file.deleteOnExit();
            out = new FileOutputStream(file);
            in = url.openStream();            byte[] buf = new byte[1024];            int len = -1;            while((len = in.read(buf))!=-1){
                out.write(buf, 0, len);
                out.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {            if(out!=null){                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }            if(in!=null){                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }    /**
     * 從sdcard中獲取圖片  */
    private Drawable readFromSdcard(File file) throws Exception {
        FileInputStream in = new FileInputStream(file);        return Drawable.createFromStream(in, file.getName());
    }

    @Override    protected void onPostExecute(Object result) {        super.onPostExecute(result);
        Drawable drawable = (Drawable) result;        if (mImageView != null && drawable != null) {
            mImageView.setBackgroundDrawable(drawable);
        }
    }

    @Override    protected void onProgressUpdate(Integer... values) {        super.onProgressUpdate(values);
    }

    @Override    protected void onCancelled() {        super.onCancelled();
    }

}

Android 實現異步加載圖片

這個ImageDownloader2的使用也很簡單

Android 實現異步加載圖片

public class ImageUtil {    /**
     * p_w_picpath loader     */
    static ImageDownloader2 loader = null;    
    /**
     * load p_w_picpath*/
    public static void loadImage(String url,final ImageView p_w_picpathView){        if(loader == null){
            loader = new ImageDownloader2();
        }
        loader.loadDrawable(url, new ImageCallback() {
            
            @Override            public void p_w_picpathLoaded(Drawable p_w_picpathDrawable) {                if(p_w_picpathDrawable!=null){
                    p_w_picpathView.setBackgroundDrawable(p_w_picpathDrawable);
                }
            }
        });
    }
    
}

Android 實現異步加載圖片

每次在使用是需要調用ImageUtil.loadImage(url,p_w_picpathView)將圖片url已經需要顯示圖片的控件ImageView的引用傳入就可以了.

 


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女