Android學習筆記————非同步圖片載入

來源:互聯網
上載者:User

我們在開發網路應用的時候,時常會涉及到圖片下載的情況,圖片下載是一個耗時的過程。由於非同步下載的體驗好,因此非同步載入網狀圖片成了我們首選的方式。

之前翻閱了網上的一些資料,發現已經有人分享了這方面的經驗,小弟在學習之餘,在他們的基礎上,也做了一些最佳化。下面我們就來看看這非同步載入的實現過程吧。

非同步載入說白了就是開後台線程來下載圖片,等待下載完成後就在UI上顯示出來。那麼我們要為每個圖片都開一個線程嗎?如果要載入一百張圖片呢?如果這樣做就顯得太浪費,這時我們就想到了線程池了!線程池可以通過反覆調度現有的線程來最大化的利用資源,我們可以通過Executors.newFixedThreadPool();來擷取這樣的線程池,然後用它來管理下載線程。

當然,我們很幸運,Android為我們提供了更加簡單的方式!

我們知道Android為我們提供了一個非常好用的非同步任務——AsyncTask,通過查看AsyncTask的源碼,我們看到了下面這行代碼:

private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,            MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);

其中,CORE_POOL_SIZE就限定了啟動並執行線程的數量。

這說明了AsyncTask內部的實現就是通過線程池來進行調度的,利用它的這一個特點,再結合上面的思路,就可以用AsyncTask來為我們實現非同步載入的功能了。那麼,具體實現請看代碼,為了方便擴充和使用,我將非同步下載的功能封裝到了自訂的組件RemoteImageView中,代碼如下:

public class RemoteImageView extends ImageView{        public static HashMap<String,Bitmap> imageCache = new HashMap<String, Bitmap>();//1.作為緩衝,有其他更好的實現方式        private static final int MAX_FAIL_TIME = 5;    private int mFails = 0;        private String mUrl;        public RemoteImageView(Context context, AttributeSet attrs) {        super(context, attrs);    }        public void setDefaultImage(int resId){        this.setImageResource(resId);    }        public void setImageUrl(String url){                if(mUrl != null && mUrl.equals(url)){            mFails++;        }else{            mFails = 0;            mUrl = url;        }                if(mFails >= MAX_FAIL_TIME)            return;                mUrl = url;                if(isCached(url))            return;                startDownload(url);    }        public boolean isCached(String url){        if(imageCache.containsKey(url)){            this.setImageBitmap(imageCache.get(url));            return true;        }                return false;    }        private void startDownload(String url){        try{            new DownloadTask().execute(url);        }catch (RejectedExecutionException e) {            //2.捕獲RejectedExecutionException同時載入的圖片過多而導致程式崩潰        }    }        private void reDownload(String url){        setImageUrl(url);    }        class DownloadTask extends AsyncTask<String, Void, String>{        private String imageUrl;                @Override        protected String doInBackground(String... params) {            imageUrl = params[0];            InputStream is = null;            Bitmap bmp = null;                        try {                URL url = new URL(imageUrl);                is = url.openStream();                bmp = BitmapFactory.decodeStream(is);                if(bmp != null){                    imageCache.put(imageUrl, bmp);                }else{                    reDownload(imageUrl);                }            } catch (MalformedURLException e) {                e.printStackTrace();            } catch (IOException e) {                e.printStackTrace();            } finally {                if(is != null){                    try {                        is.close();                    } catch (IOException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }            }                        return imageUrl;        }        @Override        protected void onPostExecute(String result) {            Bitmap bmp = null;            if(imageCache.containsKey(result)){                bmp = imageCache.get(result);                RemoteImageView.this.setImageBitmap(bmp);            }else{                reDownload(imageUrl);            }                        super.onPostExecute(result);        }            }}

這裡我主要對注釋的兩處作解釋:

1、由於圖片資源是比較消耗流量的,所以下載到本地後我們需要對其進行緩衝,緩衝的方式有多種,其中比較收歡迎的有:(1)、通過SoftReference進行臨時儲存,由於SoftReference會針對記憶體進行最佳化,所以處於記憶體最佳化,這是一種很好的方式。(2)、通過檔案進行儲存的外部儲存空間。

2、由於線程池對線程的個數有限制,當載入圖片數量過多時,會拋出RejectedExecutionException

這樣我們就能使用RemoteImageView實現圖片的非同步載入了,如有什麼錯誤,歡迎指正~~~~

下面是一個demo工程的源碼:http://download.csdn.net/download/chenshaoyang0011/4428075

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.