溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Thinking in Google Doc-圖片框架的實(shí)現(xiàn)及布局優(yōu)化

發(fā)布時(shí)間:2020-06-03 14:53:06 來(lái)源:網(wǎng)絡(luò) 閱讀:491 作者:屠夫章哥 欄目:移動(dòng)開發(fā)

學(xué)習(xí)谷歌文檔,總結(jié)如下:


1.圖片加載框架的封裝

    1)利用HttpURLConnection來(lái)封裝網(wǎng)絡(luò)加載圖片的方法

    2)創(chuàng)建自定義的AsyncTask來(lái)封裝1)中加載網(wǎng)絡(luò)圖片的方法,并顯示到控件上。

    3)暴露方法封裝2)中自定義的加載并顯示圖片的AsyncTask

    走完上面這幾步,只需調(diào)用一個(gè)方法,就可以從網(wǎng)絡(luò)上加載一張圖片并且顯示到控件上了。

  

  解決List并發(fā)下載圖片錯(cuò)位的問(wèn)題     

  但是,谷歌文檔中說(shuō)上面代碼會(huì)存在一個(gè)問(wèn)題。就是如果在List里使用,復(fù)用的話,可能會(huì)發(fā)生圖

  圖片錯(cuò)位的問(wèn)題:就是某個(gè)item顯示的圖片,可能顯示的圖片是之前的item的圖片。因?yàn)橹暗倪@

  張圖片可能加載時(shí)間比較長(zhǎng),滑動(dòng)后p_w_picpathview是復(fù)用的,所以后面的item可能會(huì)顯示之前的item的

  圖片。


  這種就是由于并發(fā)產(chǎn)生的問(wèn)題,谷歌工程師是這么解決問(wèn)題的:

  1》定義一個(gè)類 class DownloadedDrawable extends ColorDrawable,然后將下載的異步任務(wù)

    DownloadAsyncTask與其綁定起來(lái)。

    public static void     display(Context context,String url, ImageView p_w_picpathView) {
        Bitmap bitmapFromMemCache = LruCacheUtil.getBitmapFromMemCache(url);
        if(bitmapFromMemCache != null){
            p_w_picpathView.setImageBitmap(bitmapFromMemCache);
        }else{
            if (cancelPotentialDownload(url, p_w_picpathView)) {
                BitmapDownloaderTask task = new BitmapDownloaderTask(context,p_w_picpathView);
                DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
                p_w_picpathView.setImageDrawable(downloadedDrawable);
                task.execute(url);
            }
        }
    }

  2》定義2個(gè)方法 

    BitmapDownloaderTask getBitmapDownloaderTask(ImageView p_w_picpathView) 

     --得到與ImageView綁定的異步下載任務(wù)   

    public static     BitmapDownloaderTask getBitmapDownloaderTask(ImageView p_w_picpathView) {
        if (p_w_picpathView != null) {
            Drawable drawable = p_w_picpathView.getDrawable();
            if (drawable instanceof DownloadedDrawable) {
                DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
                return downloadedDrawable.getBitmapDownloaderTask();
            }
        }
        return null;
    }

 

    boolean cancelPotentialDownload(String url, ImageView p_w_picpathView) 

    --取消可能正在進(jìn)行的下載,并返回是否已經(jīng)取消。   

      如果與p_w_picpathView綁定的下載任務(wù)不為空,再判斷與ImageView綁定的異步下載任務(wù)的URL,如果

   為null或者是與當(dāng)前方法傳遞進(jìn)來(lái)URL不一致,說(shuō)明異步下載任務(wù)正在執(zhí)行之前的下載,就取消任

   務(wù),否則說(shuō)明任務(wù)正在執(zhí)行中且url一致,就不重新開啟任務(wù)。  

   

    private static boolean     cancelPotentialDownload(String url, ImageView p_w_picpathView) {
        BitmapDownloaderTask bitmapDownloaderTask = BitmapDownloaderTask.getBitmapDownloaderTask(p_w_picpathView);
    
        if (bitmapDownloaderTask != null) {
            String bitmapUrl = bitmapDownloaderTask.url;
            if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
                bitmapDownloaderTask.cancel(true);
            } else {
                // The same URL is already being downloaded.
                return false;
            }
        }
        return true;
    }

   解決圖片緩存的問(wèn)題  

    1》用內(nèi)存來(lái)緩存,使用LruCache這個(gè)類。

     內(nèi)存的特點(diǎn):

       內(nèi)存加載速度比較快,但是內(nèi)存在開關(guān)機(jī)之后會(huì)被回收,緩存的數(shù)據(jù)會(huì)消失。

     底層:

      LinkedHashMap來(lái)實(shí)現(xiàn)存儲(chǔ)    

     實(shí)現(xiàn)原理:

       當(dāng)從url下載圖片之前,先判斷緩存中存不存在圖片,如果存在直接加載圖片,不存在則

      去網(wǎng)絡(luò)請(qǐng)求圖片。

       當(dāng)AsyncTask下載完圖片之后,如果不為null,就存放到緩存中。

      于是我寫了個(gè)工具類LruCacheUtils來(lái)完成圖片的緩存

      

      

    public class     LruCacheUtil {
        //LruCache for bitmap
        private static LruCache<String, Bitmap> mMemoryCache;
        static {
            // Get max available VM memory, exceeding this amount will throw an
            // OutOfMemory exception. Stored in kilobytes as LruCache takes an
            // int in its constructor.
            final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
    
            // Use 1/8th of the available memory for this memory cache.
            final int cacheSize = maxMemory / 8;
    
            mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
                @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
                @Override
                protected int sizeOf(String key, Bitmap bitmap) {
                    // The cache size will be measured in kilobytes rather than
                    // number of items.
                    return bitmap.getByteCount() / 1024;
                }
            };
        }
    
        public static void addBitmapToMemoryCache(String key, Bitmap bitmap) {
            if (getBitmapFromMemCache(key) == null) {
                mMemoryCache.put(key, bitmap);
            }
        }
    
        public static Bitmap getBitmapFromMemCache(String key) {
            return mMemoryCache.get(key);
        }
    }

   2》使用磁盤(Disk)來(lái)緩存,使用DiskLruCache(這個(gè)類google文檔里并沒有提供)

     Android DiskLruCache 源碼解析 硬盤緩存的絕佳方案

    http://blog.csdn.net/lmj623565791/article/details/47251585

    下載鏈接

     http://http://www.oschina.net/p/disklrucache

    Android本地緩存DiskLruCache完整詳細(xì)學(xué)習(xí)示例

    http://www.2cto.com/kf/201501/368172.html 

     

    雖然利用內(nèi)存來(lái)緩存,加載圖片的時(shí)候速度比較快,但是像GridView會(huì)很快地占滿內(nèi)存。當(dāng)應(yīng)

     用非正常關(guān)閉(如被電話應(yīng)用打斷、運(yùn)行在后臺(tái)的時(shí)候被殺死)會(huì)導(dǎo)致cache被銷毀清空。

     注意:獲取圖片應(yīng)該在后臺(tái)進(jìn)行 

      Of course, fetching p_w_picpaths from disk is slower than loading from memory and should be done in a       

                      background thread, as disk read times can be unpredictable.(from google doc)

      

     緩存位置:

       有外部存儲(chǔ)設(shè)備就存放到外部存儲(chǔ)設(shè)備中,否則存放到應(yīng)用包名目錄下。


2.布局優(yōu)化

   sdk下的一些工具并不是專門針對(duì)Eclipse的,Android Studio也可以使用。  

   sdk/tools下的工具Hierarchy Viewer

   http://wear.techbrood.com/training/improving-layouts/optimizing-layout.html#Inspect

   爽處1:可以查看布局結(jié)構(gòu)某個(gè)節(jié)點(diǎn)的3個(gè)方法Measure、Layout、Draw執(zhí)行所需要的時(shí)間,這樣

        如果某個(gè)item的加載時(shí)間比較長(zhǎng),你就應(yīng)該要優(yōu)化了。

        

   使用這個(gè)工具可能會(huì)遇到的問(wèn)題:

   問(wèn)題:使用Hierarchyviewer,measure、layout、draw時(shí)間未顯示?

   解決辦法:點(diǎn)擊菜單 Profile Node,重新加載之后就有了 

用Hierarchyviewer,measure、layout、draw時(shí)間未顯示? 

         

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI