NetworkImageView.java revision da703141dabd9cae3f71e15a4b9cbb79f6d5d4b8
1/** 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package com.android.volley.toolbox; 17 18import android.content.Context; 19import android.text.TextUtils; 20import android.util.AttributeSet; 21import android.widget.ImageView; 22 23import com.android.volley.toolbox.ImageLoader.ImageContainer; 24 25/** 26 * Handles fetching an image from a URL as well as the life-cycle of the 27 * associated request. 28 */ 29public class NetworkImageView extends ImageView { 30 /** The URL of the network image to load */ 31 private String mUrl; 32 33 /** 34 * Resource ID of the image to be used as a placeholder until the network image is loaded. 35 */ 36 private int mDefaultImageId; 37 38 /** 39 * Resource ID of the image to be used if the network response fails. 40 */ 41 private int mErrorImageId; 42 43 /** Local copy of the ImageLoader. */ 44 private ImageLoader mImageLoader; 45 46 /** Current ImageContainer. (either in-flight or finished) */ 47 private ImageContainer mImageContainer; 48 49 public NetworkImageView(Context context) { 50 this(context, null); 51 } 52 53 public NetworkImageView(Context context, AttributeSet attrs) { 54 this(context, attrs, 0); 55 } 56 57 public NetworkImageView(Context context, AttributeSet attrs, int defStyle) { 58 super(context, attrs, defStyle); 59 } 60 61 /** 62 * Sets URL of the image that should be loaded into this view. Note that calling this will 63 * immediately either set the cached image (if available) or the default image specified by 64 * {@link NetworkImageView#setDefaultImageResId(int)} on the view. 65 * 66 * NOTE: If applicable, {@link NetworkImageView#setDefaultImageResId(int)} and 67 * {@link NetworkImageView#setErrorImageResId(int)} should be called prior to calling 68 * this function. 69 * 70 * @param url The URL that should be loaded into this ImageView. 71 * @param imageLoader ImageLoader that will be used to make the request. 72 */ 73 public void setImageUrl(String url, ImageLoader imageLoader) { 74 mUrl = url; 75 mImageLoader = imageLoader; 76 // The URL has potentially changed. See if we need to load it. 77 loadImageIfNecessary(); 78 } 79 80 /** 81 * Sets the default image resource ID to be used for this view until the attempt to load it 82 * completes. 83 */ 84 public void setDefaultImageResId(int defaultImage) { 85 mDefaultImageId = defaultImage; 86 } 87 88 /** 89 * Sets the error image resource ID to be used for this view in the event that the image 90 * requested fails to load. 91 */ 92 public void setErrorImageResId(int errorImage) { 93 mErrorImageId = errorImage; 94 } 95 96 /** 97 * Loads the image for the view if it isn't already loaded. 98 */ 99 private void loadImageIfNecessary() { 100 int width = getWidth(); 101 int height = getHeight(); 102 103 // if the view's bounds aren't known yet, hold off on loading the image. 104 if (width == 0 && height == 0) { 105 return; 106 } 107 108 // if the URL to be loaded in this view is empty, cancel any old requests and clear the 109 // currently loaded image. 110 if (TextUtils.isEmpty(mUrl)) { 111 if (mImageContainer != null) { 112 mImageContainer.cancelRequest(); 113 mImageContainer = null; 114 } 115 setImageBitmap(null); 116 return; 117 } 118 119 // if there was an old request in this view, check if it needs to be canceled. 120 if (mImageContainer != null && mImageContainer.getRequestUrl() != null) { 121 if (mImageContainer.getRequestUrl().equals(mUrl)) { 122 // if the request is from the same URL, return. 123 return; 124 } else { 125 // if there is a pre-existing request, cancel it if it's fetching a different URL. 126 mImageContainer.cancelRequest(); 127 setImageBitmap(null); 128 } 129 } 130 131 // The pre-existing content of this view didn't match the current URL. Load the new image 132 // from the network. 133 ImageContainer newContainer = mImageLoader.get(mUrl, 134 ImageLoader.getImageListener(this, mDefaultImageId, mErrorImageId)); 135 136 // update the ImageContainer to be the new bitmap container. 137 mImageContainer = newContainer; 138 } 139 140 @Override 141 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 142 super.onLayout(changed, left, top, right, bottom); 143 loadImageIfNecessary(); 144 } 145 146 @Override 147 protected void onDetachedFromWindow() { 148 if (mImageContainer != null) { 149 // If the view was bound to an image request, cancel it and clear 150 // out the image from the view. 151 mImageContainer.cancelRequest(); 152 setImageBitmap(null); 153 // also clear out the container so we can reload the image if necessary. 154 mImageContainer = null; 155 } 156 super.onDetachedFromWindow(); 157 } 158 159 @Override 160 protected void drawableStateChanged() { 161 super.drawableStateChanged(); 162 invalidate(); 163 } 164} 165