Android圖片載入的框架Fresco使用詳解

子墨部落格發表於2015-08-06

我們接著上文繼續說,上篇部落格中我們已經知道了Fresco怎麼用,也知道了它的很多屬性,但是很多時候xml檔案是不能滿足你的要求的,這就需要你在程式碼中動態的改變顯示的內容,今天我們就來探索一下如何在程式碼中改變圖片實現的狀態和內容

前面我們已經使用過SimpleDraweeView這個控制元件了,顯示圖片的時候直接寫了一個setImageURI(uri),Fresco不僅僅提供了這一個方法來顯示圖片,它還提供了setController(controller)方法載入圖片

DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setUri(uri)
                .build();
        imageView.setController(controller);

當然如果你想監聽載入的過程,就加一個ControllerListen

ControllerListener listener = new BaseControllerListener(){
            @Override
            public void onFinalImageSet(String id, Object imageInfo, Animatable animatable) {
                super.onFinalImageSet(id, imageInfo, animatable);
            }

            @Override
            public void onFailure(String id, Throwable throwable) {
                super.onFailure(id, throwable);
            }

            @Override
            public void onIntermediateImageFailed(String id, Throwable throwable) {
                super.onIntermediateImageFailed(id, throwable);
            }
        };
        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setUri(uri)
                .setControllerListener(listener)
                .build();
        imageView.setController(controller);

圖片載入成功或者失敗,會執行裡面的方法,其中圖片載入成功時會執行onFinalImageSet方法,圖片載入失敗時會執行onFailure方法,如果圖片設定漸進式,onIntermediateImageFailed會被回撥

說完了如何載入uri之後,如何實現在xml中的效果呢?我們繼續在java程式碼中實現xml的效果

GenericDraweeHierarchy hierarchy = new GenericDraweeHierarchyBuilder(getResources())
                .setFadeDuration(300)
                .setBackground(getDrawable(R.drawable.ic_launcher))
                .setPlaceholderImage(getDrawable(R.drawable.ic_launcher))
                .setFailureImage(getDrawable(R.drawable.ic_launcher))
                .build();
        imageView.setHierarchy(hierarchy);

方法很多,你在xml中用到的都可以在這裡設定,有些在xml中不能設定的在這裡也是可以的,例如,我可以設定多張背景圖片,我可以設定多張疊加圖,這裡都可以幫你實現,是不是很強大啊,想不想拿到特權了一樣呢!但是DraweeHiererchy建立時比較耗時,所以要多次利用

 GenericDraweeHierarchy hierarchy1 = imageView.getHierarchy();

這個框架不僅僅是這些東西,它還有很多更牛逼的東西,例如:它提供了漸進式載入圖片,顯示gif動畫圖片等等

首先是漸進式圖片載入,這方面的功能充分考慮了網路比較慢的情況下,使用者不至於一致在等,最起碼能看到模糊的照片,這個所謂的漸進式載入就是說使用者從圖片載入之後,圖片會從模糊到清晰的一個漸變過程,當然這個過程僅限於從網路載入圖片,本地或者快取等地方的圖片也不需要漸進式載入,沒有意義

ProgressiveJpegConfig config = new ProgressiveJpegConfig() {
            @Override
            public int getNextScanNumberToDecode(int i) {
                return 0;
            }

            @Override
            public QualityInfo getQualityInfo(int i) {
                return null;
            }
        };

        ImagePipelineConfig imagePipelineConfig = ImagePipelineConfig.newBuilder(this)
                .setProgressiveJpegConfig(config)
                .build();
        Fresco.initialize(getApplicationContext(),imagePipelineConfig);
當然你也可以使用ProgressiveJpegConfig config1= new SimpleProgressiveJpegConfig(list,2);
FLog.setMinimumLoggingLevel(FLog.VERBOSE);
        Set<RequestListener> listeners = new HashSet<>();
        listeners.add(new RequestLoggingListener());
        ImagePipelineConfig config = ImagePipelineConfig.newBuilder(this)
                .setRequestListeners(listeners)
                .build();
        Fresco.initialize(this, config);
        setContentView(R.layout.activity_main);

        mProgressiveJpegView = (SimpleDraweeView) findViewById(R.id.my_image_view);

        Uri uri = Uri.parse("http://pooyak.com/p/progjpeg/jpegload.cgi?o=1");
        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                .setProgressiveRenderingEnabled(true)
                .build();
        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setImageRequest(request)
                .build();
        mProgressiveJpegView.setController(controller);
ImageRequest request = ImageRequestBuilder
                .newBuilderWithSource(uri)
                .setProgressiveRenderingEnabled(true)
                .build();
        PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder()
                .setImageRequest(request)
                .setOldController(imageView.getController())
                .build();
        imageView.setController(controller);

哎吆,不錯哦,可是這個image pipeline這個又是個什麼啊?它的來頭比較大,負責圖片的載入工作

1.檢查記憶體快取,如有,返回

2.後臺執行緒開始後續工作

3.檢查是否在未解碼記憶體快取中。如有,解碼,變換,返回,然後快取到記憶體快取中。

4.檢查是否在檔案快取中,如果有,變換,返回。快取到未解碼快取和記憶體快取中。

5.從網路或者本地載入。載入完成後,解碼,變換,返回。存到各個快取中。

繼續看gif圖片,其實跟顯示圖片沒什麼差,主要是動態圖片涉及到的動畫的停止與播放,如果只是單純的試用一下,那就直接在controller裡面設定setAutoPlayAnimation為true,如果你想手動監聽就new一個ControllerListener裡面手動控制

當我們要從伺服器端下載一張高清圖片,圖片比較大,下載很慢的情況下有些伺服器會提供一張縮圖,同樣的Fresco也支援這種方法,在controller中提供了兩個不同的方法setLowResImageRequest和setImageRequest,看到方法名你應該明白了怎麼用

個人認為這個框架最巧妙的地方,就是把bitmap儲存到ashmen,不會啟動gc,使的介面不會因為gc而卡死,Fresco使用三級快取,第一級快取就是儲存bitmap,第二級快取儲存在記憶體,但是沒有解碼,使用時需要介面,第三級快取就是儲存在本地檔案,同樣檔案也未解碼,使用的時候要先解碼啦!

上面談到的儲存的很多內容都未解碼,這也是fresco預設使用3個執行緒的原因,一個執行緒用來載入uri,一個執行緒用來解碼,最後一個你知道它做什麼,其餘你想了解的東西自己去官網找找。

相關文章