【第三篇】Volley圖片加載之NetworkImageView代碼分析

Volley的使用之加載圖片 講過使用NetWorkImageView進行圖片加載的例子,本文着重講解NetWorkImageView內部是如何實現的,以及Volley這個控件有什麼特性。
 
1,經過幾個構造方法,可見NetworkImageView並無添加本身的自定義屬性,而是繼承自Imageview的自定義屬性。
 
2,而後是 setImageUrl ( String url , ImageLoader imageLoader ),第一個參數爲網絡圖片url,第二個參數爲Imageloader對象,通常咱們在開發過程當中會以下使用NetWorkImageView。
1         load_img =(NetworkImageView) findViewById(R.id.load_img);
2         lruImageCache =LruImageCache.getInstance();
3         requestQueue =Volley.newRequestQueue(this);
4         imageLoader =newImageLoader(requestQueue, lruImageCache);
5         load_img.setImageUrl(IMGURL, imageLoader);

 

其中setImageUrl方法中會去調用loadImageIfNecessary(false)方法;那就着重看下這個方法:
第 73行,74行,獲取當前NetWorkImageView的組件寬高;
 
第91行到98行,如何傳進來的url爲null,就會取消圖片加載請求,並設置默認的圖片給NetWorkImageView;
 
調用155-166行代碼, mDefaultImageId是經過setDefaultImageResId(int defaultImage)方法傳遞進來的,(由此能夠能夠看出,有必要設置一個默認的圖片在NetWorkImageView中,防止在圖片url爲null的狀況下的不友好的界面顯示效果),不然調用ImagView的setImageBitmap(null)代碼;
 
100-111行代碼是判斷是否該NetworkImageView重複調用過該圖片url,若是重複調用return掉,若是如今調用的圖片url和之前的圖片url不一樣,cannel掉之前的圖片加載,並設置默認的圖片給該NetworkImageView。
 
mImageLoader.get方法其實要穿進去組件的寬高,裏面有兩個回調函數,分別處理加載成功和加載失敗狀況下的問題處理,若是失敗調用onErrorResponse,不然調用onResponse,表示獲取圖片的相關信息了,而後看失敗裏面調用的是 setErrorImageResId(int errorImage),其實這個圖片也是能夠從外面經過參數設置在加載圖片失敗的狀況下的圖片顯示。
 
143-140行,若是獲取到圖片,按照尺寸加載圖片,不然按照尺寸加載默認圖片。
 
171-181行代碼是表示當屏幕劃出,   cannel前面的請求。
  1 public class NetworkImageView extends ImageView {
  2     /** The URL of the network image to load */
  3     private String mUrl;
  4 
  5     /**
  6      * Resource ID of the image to be used as a placeholder until the network image is loaded.
  7      */
  8     private int mDefaultImageId;
  9 
 10     /**
 11      * Resource ID of the image to be used if the network response fails.
 12      */
 13     private int mErrorImageId;
 14 
 15     /** Local copy of the ImageLoader. */
 16     private ImageLoader mImageLoader;
 17 
 18     /** Current ImageContainer. (either in-flight or finished) */
 19     private ImageContainer mImageContainer;
 20 
 21     public NetworkImageView(Context context) {
 22         this(context, null);
 23     }
 24 
 25     public NetworkImageView(Context context, AttributeSet attrs) {
 26         this(context, attrs, 0);
 27     }
 28 
 29     public NetworkImageView(Context context, AttributeSet attrs, int defStyle) {
 30         super(context, attrs, defStyle);
 31     }
 32 
 33     /**
 34      * Sets URL of the image that should be loaded into this view. Note that calling this will
 35      * immediately either set the cached image (if available) or the default image specified by
 36      * {@link NetworkImageView#setDefaultImageResId(int)} on the view.
 37      *
 38      * NOTE: If applicable, {@link NetworkImageView#setDefaultImageResId(int)} and
 39      * {@link NetworkImageView#setErrorImageResId(int)} should be called prior to calling
 40      * this function.
 41      *
 42      * @param url The URL that should be loaded into this ImageView.
 43      * @param imageLoader ImageLoader that will be used to make the request.
 44      */
 45     public void setImageUrl(String url, ImageLoader imageLoader) {
 46         mUrl = url;
 47         mImageLoader = imageLoader;
 48         // The URL has potentially changed. See if we need to load it.
 49         loadImageIfNecessary(false);
 50     }
 51 
 52     /**
 53      * Sets the default image resource ID to be used for this view until the attempt to load it
 54      * completes.
 55      */
 56     public void setDefaultImageResId(int defaultImage) {
 57         mDefaultImageId = defaultImage;
 58     }
 59 
 60     /**
 61      * Sets the error image resource ID to be used for this view in the event that the image
 62      * requested fails to load.
 63      */
 64     public void setErrorImageResId(int errorImage) {
 65         mErrorImageId = errorImage;
 66     }
 67 
 68     /**
 69      * Loads the image for the view if it isn't already loaded.
 70      * @param isInLayoutPass True if this was invoked from a layout pass, false otherwise.
 71      */
 72     void loadImageIfNecessary(final boolean isInLayoutPass) {
 73         int width = getWidth();
 74         int height = getHeight();
 75 
 76         boolean wrapWidth = false, wrapHeight = false;
 77         if (getLayoutParams() != null) {
 78             wrapWidth = getLayoutParams().width == LayoutParams.WRAP_CONTENT;
 79             wrapHeight = getLayoutParams().height == LayoutParams.WRAP_CONTENT;
 80         }
 81 
 82         // if the view's bounds aren't known yet, and this is not a wrap-content/wrap-content
 83         // view, hold off on loading the image.
 84         boolean isFullyWrapContent = wrapWidth && wrapHeight;
 85         if (width == 0 && height == 0 && !isFullyWrapContent) {
 86             return;
 87         }
 88 
 89         // if the URL to be loaded in this view is empty, cancel any old requests and clear the
 90         // currently loaded image.
 91         if (TextUtils.isEmpty(mUrl)) {
 92             if (mImageContainer != null) {
 93                 mImageContainer.cancelRequest();
 94                 mImageContainer = null;
 95             }
 96             setDefaultImageOrNull();
 97             return;
 98         }
 99 
100         // if there was an old request in this view, check if it needs to be canceled.
101         if (mImageContainer != null && mImageContainer.getRequestUrl() != null) {
102             if (mImageContainer.getRequestUrl().equals(mUrl)) {
103                 // if the request is from the same URL, return.
104                 return;
105             } else {
106                 // if there is a pre-existing request, cancel it if it's fetching a different URL.
107                 mImageContainer.cancelRequest();
108                 setDefaultImageOrNull();
109             }
110         }
111 
112         // Calculate the max image width / height to use while ignoring WRAP_CONTENT dimens.
113         int maxWidth = wrapWidth ? 0 : width;
114         int maxHeight = wrapHeight ? 0 : height;
115 
116         // The pre-existing content of this view didn't match the current URL. Load the new image
117         // from the network.
118         ImageContainer newContainer = mImageLoader.get(mUrl,
119                 new ImageListener() {
120                     @Override
121                     public void onErrorResponse(VolleyError error) {
122                         if (mErrorImageId != 0) {
123                             setImageResource(mErrorImageId);
124                         }
125                     }
126 
127                     @Override
128                     public void onResponse(final ImageContainer response, boolean isImmediate) {
129                         // If this was an immediate response that was delivered inside of a layout
130                         // pass do not set the image immediately as it will trigger a requestLayout
131                         // inside of a layout. Instead, defer setting the image by posting back to
132                         // the main thread.
133                         if (isImmediate && isInLayoutPass) {
134                             post(new Runnable() {
135                                 @Override
136                                 public void run() {
137                                     onResponse(response, false);
138                                 }
139                             });
140                             return;
141                         }
142 
143                         if (response.getBitmap() != null) {
144                             setImageBitmap(response.getBitmap());
145                         } else if (mDefaultImageId != 0) {
146                             setImageResource(mDefaultImageId);
147                         }
148                     }
149                 }, maxWidth, maxHeight);
150 
151         // update the ImageContainer to be the new bitmap container.
152         mImageContainer = newContainer;
153     }
154 
155     private void setDefaultImageOrNull() {
156         if(mDefaultImageId != 0) {
157             setImageResource(mDefaultImageId);
158         }
159         else {
160             setImageBitmap(null);
161         }
162     }
163 
164     @Override
165     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
166         super.onLayout(changed, left, top, right, bottom);
167         loadImageIfNecessary(true);
168     }
169 
170     @Override
171     protected void onDetachedFromWindow() {
172         if (mImageContainer != null) {
173             // If the view was bound to an image request, cancel it and clear
174             // out the image from the view.
175             mImageContainer.cancelRequest();
176             setImageBitmap(null);
177             // also clear out the container so we can reload the image if necessary.
178             mImageContainer = null;
179         }
180         super.onDetachedFromWindow();
181     }
182 
183     @Override
184     protected void drawableStateChanged() {
185         super.drawableStateChanged();
186         invalidate();
187     }
188 }
相關文章
相關標籤/搜索