[Android]Volley原始碼分析(店)應用

來源:互聯網
上載者:User

標籤:

通過前面的談話,我相信你有Volley有了一定的瞭解了原理。本章將給出一些我們的應用程式都可以在樣品中直接使用,第一樣品是

NetworkImageView類,事實上NetworkImageView顧名思義就是將非同步操作封裝在了控制項本身,這樣的設計能夠充分保留控制項的移植性和維護性。

NetworkImageView通過調用setImageUrl來指定詳細的url:

public void setImageUrl(String url, ImageLoader imageLoader) {        mUrl = url;        mImageLoader = imageLoader;        // The URL has potentially changed. See if we need to load it.        loadImageIfNecessary(false);    }

void loadImageIfNecessary(final boolean isInLayoutPass) {        int width = getWidth();        int height = getHeight();        boolean wrapWidth = false, wrapHeight = false;        if (getLayoutParams() != null) {            wrapWidth = getLayoutParams().width == LayoutParams.WRAP_CONTENT;            wrapHeight = getLayoutParams().height == LayoutParams.WRAP_CONTENT;        }        // if the view's bounds aren't known yet, and this is not a wrap-content/wrap-content        // view, hold off on loading the image.        boolean isFullyWrapContent = wrapWidth && wrapHeight;        if (width == 0 && height == 0 && !isFullyWrapContent) {            return;        }        // if the URL to be loaded in this view is empty, cancel any old requests and clear the        // currently loaded image.        if (TextUtils.isEmpty(mUrl)) {            if (mImageContainer != null) {                mImageContainer.cancelRequest();                mImageContainer = null;            }            setDefaultImageOrNull();            return;        }        // if there was an old request in this view, check if it needs to be canceled.        if (mImageContainer != null && mImageContainer.getRequestUrl() != null) {            if (mImageContainer.getRequestUrl().equals(mUrl)) {                // if the request is from the same URL, return.                return;            } else {                // if there is a pre-existing request, cancel it if it's fetching a different URL.                mImageContainer.cancelRequest();                setDefaultImageOrNull();            }        }        // Calculate the max image width / height to use while ignoring WRAP_CONTENT dimens.        int maxWidth = wrapWidth ?

0 : width; int maxHeight = wrapHeight ?

0 : height; // The pre-existing content of this view didn't match the current URL. Load the new image // from the network. ImageContainer newContainer = mImageLoader.get(mUrl, new ImageListener() { @Override public void onErrorResponse(VolleyError error) { if (mErrorImageId != 0) { setImageResource(mErrorImageId); } } @Override public void onResponse(final ImageContainer response, boolean isImmediate) { // If this was an immediate response that was delivered inside of a layout // pass do not set the image immediately as it will trigger a requestLayout // inside of a layout. Instead, defer setting the image by posting back to // the main thread. if (isImmediate && isInLayoutPass) { post(new Runnable() { @Override public void run() { onResponse(response, false); } }); return; } if (response.getBitmap() != null) { setImageBitmap(response.getBitmap()); } else if (mDefaultImageId != 0) { setImageResource(mDefaultImageId); } } }, maxWidth, maxHeight); // update the ImageContainer to be the new bitmap container. mImageContainer = newContainer; }


我們從這段邏輯不難看出,url這個屬性的持有人是ImageContainer.當Bitmap相應的url與Container相應的url同樣的時候,Volley將直接返回。

否則將通過一個叫做ImageLoader的對象get.

ImageContainer newContainer = mImageLoader.get(mUrl,                new ImageListener() {                    @Override                    public void onErrorResponse(VolleyError error) {                        if (mErrorImageId != 0) {                            setImageResource(mErrorImageId);                        }                    }                    @Override                    public void onResponse(final ImageContainer response, boolean isImmediate) {                        // If this was an immediate response that was delivered inside of a layout                        // pass do not set the image immediately as it will trigger a requestLayout                        // inside of a layout. Instead, defer setting the image by posting back to                        // the main thread.                        if (isImmediate && isInLayoutPass) {                            post(new Runnable() {                                @Override                                public void run() {                                    onResponse(response, false);                                }                            });                            return;                        }                        if (response.getBitmap() != null) {                            setImageBitmap(response.getBitmap());                        } else if (mDefaultImageId != 0) {                            setImageResource(mDefaultImageId);                        }                    }                }, maxWidth, maxHeight);
ImageLoader.get(String requestUrl, ImageListener imageListener,
            int maxWidth, int maxHeight):

public ImageContainer get(String requestUrl, ImageListener imageListener,            int maxWidth, int maxHeight) {        // only fulfill requests that were initiated from the main thread.        throwIfNotOnMainThread();        final String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight);        // Try to look up the request in the cache of remote images.        Bitmap cachedBitmap = mCache.getBitmap(cacheKey);        if (cachedBitmap != null) {            // Return the cached bitmap.            ImageContainer container = new ImageContainer(cachedBitmap, requestUrl, null, null);            imageListener.onResponse(container, true);            return container;        }        // The bitmap did not exist in the cache, fetch it!        ImageContainer imageContainer =                new ImageContainer(null, requestUrl, cacheKey, imageListener);        // Update the caller to let them know that they should use the default bitmap.        imageListener.onResponse(imageContainer, true);        // Check to see if a request is already in-flight.        BatchedImageRequest request = mInFlightRequests.get(cacheKey);        if (request != null) {            // If it is, add this request to the list of listeners.            request.addContainer(imageContainer);            return imageContainer;        }        // The request is not already in flight. Send the new request to the network and        // track it.        Request<?> newRequest =            new ImageRequest(requestUrl, new Listener<Bitmap>() {                <span style="color:#009900;">@Override                public void onResponse(Bitmap response) {                    onGetImageSuccess(cacheKey, response);                }</span>            }, maxWidth, maxHeight,            Config.RGB_565, new ErrorListener() {                @Override                public void onErrorResponse(VolleyError error) {                    onGetImageError(cacheKey, error);                }            });        mRequestQueue.add(newRequest);        mInFlightRequests.put(cacheKey,                new BatchedImageRequest(newRequest, imageContainer));        return imageContainer;    }
      ImageLoader開始的第一步你可能非常難理解,為什麼須要自己從Cache中獲得?RequestQueue不是都已經幫你做好了這些嗎?實際上這個Cache是NetworkImageView 自己定義的Cache:ImageCache。而這樣的Cache被Volley拋給使用者去實現,你能夠通過適配器模式裝飾成為你自己的Cache,也能夠裝飾成DiskBaseCache。

      通過綠色段代碼我們能夠知道當ImageLoader在Volley返回的時候回調 onGetImageSuccess(cacheKey, response)方法。

這種方法是為了補充回調ImageLoader自訂的ImageListener回調

private void batchResponse(String cacheKey, BatchedImageRequest request) {        mBatchedResponses.put(cacheKey, request);        // If we don't already have a batch delivery runnable in flight, make a new one.        // Note that this will be used to deliver responses to all callers in mBatchedResponses.        if (mRunnable == null) {            mRunnable = new Runnable() {                @Override                public void run() {                    for (BatchedImageRequest bir : mBatchedResponses.values()) {                        for (ImageContainer container : bir.mContainers) {                            // If one of the callers in the batched request canceled the request                            // after the response was received but before it was delivered,                            // skip them.                            if (container.mListener == null) {                                continue;                            }                            if (bir.getError() == null) {                                container.mBitmap = bir.mResponseBitmap;                                container.mListener.onResponse(container, false);                            } else {                                container.mListener.onErrorResponse(bir.getError());                            }                        }                    }                    mBatchedResponses.clear();                    mRunnable = null;                }            };            // Post the runnable.            mHandler.postDelayed(mRunnable, mBatchResponseDelayMs);        }    }

能夠看到,這一切的命令都發生在UI線程中。最後通過ImageListener回調來實現圖片設定。

public static ImageListener getImageListener(final ImageView view,            final int defaultImageResId, final int errorImageResId) {        return new ImageListener() {            @Override            public void onErrorResponse(VolleyError error) {                if (errorImageResId != 0) {                    view.setImageResource(errorImageResId);                }            }            @Override            public void onResponse(ImageContainer response, boolean isImmediate) {                if (response.getBitmap() != null) {                    view.setImageBitmap(response.getBitmap());                } else if (defaultImageResId != 0) {                    view.setImageResource(defaultImageResId);                }            }        };    }





著作權聲明:本文部落格原創文章。部落格,未經同意,不得轉載。

[Android]Volley原始碼分析(店)應用

聯繫我們

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