編輯:關於Android編程
通過前面的講述,相信你已經對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; }
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,
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 ListenerImageLoader開始的第一步你可能很難理解,為什麼需要自己從Cache中獲得?RequestQueue不是都已經幫你做好了這些麼?實際上這個Cache是NetworkImageView 自定義的Cache:ImageCache。而這種Cache被Volley拋給用戶去實現,你可以通過適配器模式裝飾成為你自己的Cache,也可以裝飾成DiskBaseCache。() { @Override public void onResponse(Bitmap response) { onGetImageSuccess(cacheKey, response); } }, 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在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); } }
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); } } }; }
進行如下操作: 應用信息 會到達如下界面: 可以看到這個應用占用的磁盤空間。vcD4KPHA+z8jLtb3hufujrNXivLjP7rvhvMbL48TE0KnOx
Intent組件雖然不是四大組件,但卻是連接四大組件的橋梁,學習好這個知識,也非常的重要。一、什麼是Intent1、Intent的概念:Android中提供了Intent
用過多米音樂的都市知道, 這個UI可以上下滑動,作用嘛---無聊中可以劃劃解解悶,這被錘子公司老羅稱謂為“情懷”,其實叫“情味”更
最近博主開始在項目中實踐MVP模式,卻意外發現內存洩漏比較嚴重,但卻很少人談到這個問題,促使了本文的發布,本文假設讀者已了解MVP架構。MVP簡介M-Modle,數據,邏