Android換膚功能設計與實現(5)——網路載入及圖片記憶體管理

來源:互聯網
上載者:User

    在開發Android用戶端應用時,經常要與Server端進行通訊,最常用的也是最麻煩的就是 通過網路載入各種圖片資源。由於與PC相比,手機的記憶體實在少的可憐。同時,為了提手機內同時啟動並執行任務數,Android在系統 內對虛擬機器是有最高記憶體限制的,預設在4.0上APP最高記憶體佔用為48MB,在3.0以前最高位32MB。以上就是在開發Android用戶端經常要面對的兩個最主要的問題,下面一一進行解決。

    一、網路載入技術

    想要快速的實現網路載入,可以從2各方面入手,一個是與Server端的通訊協議;第二個就是提高自身載入速度。

    首先,與Server端的通訊協議,可以採用分段載入的方式,就是在載入過程中,分為兩個階段,一個是載入整體資料的階段,另一個是載入具體資源階段。我們在瀏覽網頁時經常就是通過這種方式提高訪問速度,提升訪問體驗的。具體 就是首先擷取整個頁面的文字內容,擷取各個圖片資源的大小資訊,進行頁面的布局排版。之後根據具體瀏覽的位置,再單獨發送請求,擷取具體的圖片資源,從而實現頁面的快速顯示,同時節省網路流量。為了實現這種訪問方式,在用戶端通過Bitmap載入網狀圖片時,可以通過2段訪問的方式,及先擷取Bitmap大小,需要時再去擷取真正資源,從而大大提升頁面載入速度。

 private BitmapFactory.Options mOption;  mOption = new BitmapFactory.Options();mOption.inSampleSize = 1;   //只進行大小判斷   mOption.inJustDecodeBounds = true;   BitmapFactory.decodeStream(new URL(imageUrl).openStream(),null,mOption);  if(mOption.outHeight > 210){         mOption.inSampleSize = 4;                    }  mOption.inJustDecodeBounds = false;                                       Bitmap drawable = BitmapFactory.decodeStream(new URL(imageUrl)                            .openStream(),null,mOption);

    其次,就是用戶端在訪問Server端時,採用多線程訪問的技術,同步發起資源請求,可以大大提高資源訪問及申請的速度。這裡比較常用的手段是採用線程池來管理資源的請求與管理。線程池擁有自己的執行隊列,自動將執行請求進行隊列緩衝,按順序執行請求。線程池可以有效避免手動建立線程的線程開銷,線程池自動維護執行線程,在有執行請求時,不會銷毀執行線程。

    private ExecutorService executorService;        executorService = new ThreadPoolExecutor(CORE_THREAD_SIZE, MAX_THREAD_SIZE, 120, TimeUnit.SECONDS,                new LinkedBlockingQueue<Runnable>(),                Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardOldestPolicy());executorService.submit(new Runnable() {public void run() {}        }

    二、網狀圖片資源載入及記憶體管理

    在進行用戶端開發時,經常要面對的就是網路載入大量的圖片,而每一張圖片又是即時載入,需要手動釋放資源,否則在載入新圖片時經常出現OOM(Out of Memory)問題。同時為了介面顯示瀏覽的流暢性,又需要在一定程度上、記憶體允許範圍內的緩衝請求。如何在平衡這兩方面的問題,避免出現OOM,提高APP的穩定性那。這裡提兩個簡單有效、實用的方式。

    首先,根據具體的資源大小分別進行管理,這是在緩衝、載入中需要處理的第一個問題,需要根據具體的需求,哪些資源對緩衝的需求更強烈,那些資源對釋放更迫切。使用不同的資源訪問、管理方式。

    接下來就根據資源的簡單分類分別進行訪問、管理;對於釋放要求更迫切的資源來說,我們可以採用二級緩衝、同步釋放的方式。簡單來說就是在訪問網路資源擷取後,複製到內部固定緩衝空間,同步釋放網路載入資源。

private static Bitmap mBigBitmap[] = new Bitmap[HorizontalViewer.MAX_PREVIEW_PICS];    static{        for(int i=0;i<HorizontalViewer.MAX_PREVIEW_PICS;i++){//            mDrawBitmap[i] = Bitmap.createBitmap(IMAGE_WIDTH, IMAGE_HEIGHT, Config.ARGB_8888);            mBigBitmap[i] = Bitmap.createBitmap(BIG_IMAGE_WIDTH, BIG_IMAGE_HEIGHT, Config.ARGB_8888);        }    }Bitmap drawable = BitmapFactory.decodeStream(new URL(imageUrl)                     .openStream(),null,mOption);        mCanvas = new Canvas(mBigBitmap[inx]);        mCanvas.drawBitmapdrawable new Rect(0,0,imageDrawable.getWidth(),imageDrawable.getHeight()),                 new Rect(0,0,BIG_IMAGE_WIDTH,BIG_IMAGE_HEIGHT), null);if (!drawable.isRecycled()) {     drawable.recycle();  }

通過Canvas實現對圖片資源的快速複製,由於在複製過程中,Bitmap底層直接採用記憶體拷貝的方式進行,在效率上非常高,通過固定使用static的Bitmap緩衝池,使資源佔用在一個定值內,網路非同步載入的資源,在拷貝完後,迅速釋放,避免記憶體的過高佔用。

    而對於緩衝需求更強烈的資源來說,在訪問過程中,可以採用弱引用的方式,進行載入與管理,在系統資源滿足要求的情況下,系統不會釋放弱引用所指向的資源,在資源緊張下,自動回收若引用資源。這樣剛好滿足我們對資源緩衝的要求。

    public Map<String, WeakReference<Bitmap>> imageCache = new HashMap<String, WeakReference<Bitmap>>();    public Bitmap loadSmallDrawable(final String imageUrl, final ImageCallback callback) {        /* 方案 :小圖片的緩衝比較多 */        if (imageCache.containsKey(imageUrl)) {            WeakReference<Bitmap> softReference = imageCache.get(imageUrl);                        if (softReference.get() != null) {                if (callback != null) {                    callback.imageLoaded(softReference.get());                }                return softReference.get();            }        }        if (callback == null)            return null;        // 緩衝中沒有映像,則從網路上取出資料,並將取出的資料緩衝到記憶體中        executorService.submit(new Runnable() {            public void run() {                try {                    Bitmap drawable = BitmapFactory.decodeStream(new URL(imageUrl)                            .openStream(),null,mOption);                    drawable = Bitmap.createScaledBitmap(drawable, 120, 200, true);//                    drawable.recycle();                    imageCache.put(imageUrl, new                    WeakReference<Bitmap>(drawable));                    Log.e(TAG, "get a drawable");                    } catch (Exception e) {                    throw new RuntimeException(e);                }            }        });        return null;    }

    通過以上技術基本可以滿足Android用戶端訪問網路載入資源的需求,最後一點需要注意的就是對資源的訪問,盡量做到提前預知資源大小,盡量避免對圖片的資源的二次加工。簡單來說就是對網路載入的資源,盡量減少在內部的縮放、Alpha等的重新改變,主要由於對Bitmap的各種改變,系統都是重新建立資源,這樣就導致記憶體空間的浪費,及比較高的時間代價。在訪問資源時,通過改變採樣率等方式,有效避免這種情況的發生。

    private BitmapFactory.Options mOption;    mOption = new BitmapFactory.Options();    mOption.inSampleSize = 1;      //只進行大小判斷       mOption.inJustDecodeBounds = true;       BitmapFactory.decodeStream(new URL(imageUrl)          .openStream(),null,mOption);    if(mOption.outHeight > 210){            mOption.inSampleSize = 4;          }     mOption.inJustDecodeBounds = false;                          Bitmap drawable = BitmapFactory.decodeStream(new URL(imageUrl)               .openStream(),null,mOption);

            

                     ——歡迎轉載,請註明出處http://blog.csdn.net/zyplus——

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.