【第三篇】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 }
时间: 2024-08-06 14:26:00

【第三篇】Volley图片加载之NetworkImageView代码分析的相关文章

Android艺术——Bitmap高效加载和缓存代码分析(2)

Bitmap的加载与缓存代码分析: 图片的压缩 比如有一张1024*768像素的图像要被载入内存,然而最终你要用到的图片大小其实只有128*96,那么我们会浪费很大一部分内存,这显然是没有必要的,下面是一个实例: public static int calculateInSampleSize(              BitmapFactory.Options options, int reqWidth, int reqHeight) {      // Raw height and widt

volley中图片加载

volley图片加载有三种方式: 1. ImageRequest 1 singleImg=(ImageView)findViewById(R.id.volley_img_single_imgeview); 2 ImageRequest imgRequest=new ImageRequest(url, new Response.Listener<Bitmap>() { 3 @Override 4 public void onResponse(Bitmap arg0) { 5 // TODO Au

android 图片加载优化,避免oom问题产生

1,及时回收bitmap,在activity的onstop()和onDestory()里面调用如下代码进行bitmap的回收: // 先判断是否已经回收 if(bitmap != null && !bitmap.isRecycled()){ // 回收并且置为null bitmap.recycle(); bitmap = null; } System.gc(); 2,对oom异常的捕获:出现异常不能让程序就那么崩掉吧,所以对程序中中设计bitmap的操作都要检测oom异常进而进行处理: B

主流图片加载框架ImageLoader、Glide、Picasso、Fresco性能分析---图片加载速度比较

图片加载这种实现繁琐,可复用性又极强的东西,自然是选择使用图片加载框架来快速实现. 像是Android-Universal-Image-Loader.Glide.Picasso.Fresco之类, 但是这时候的烦恼在于,这么多图片加载框架到底谁最实用? 有说Fresco,因为支持WebP,还是用了NDK来加载图片,减少JavaHeap的使用 有Picasso,简洁高效 有说Glide,Picasso升级,可以加载Gif,在Picasso基础上扩展了很多方法 ImageLoader 使用最广,因为

android webView 图片加载不出来 后台报错Uncaught TypeError: Cannot call method &#39;getElementsByTagName&#39; of null

在之前,webView加载图片完全没有问题.直到前端H5开发换新的加载图片的方式,导致图片忽然加载不出来了. 从后台日志看到了webview 打印了报错信息 Cannot call method 'getElementsByTagName' of null 我怀疑是不是由于此处报错终止了图片加载的进程. 分析此处错误出现的原因: 由于调用的H5界面的js其中的写法不规范,webView在加载的时候,调用的doom模型为空,导致了其图片没有加载出来 解决办法: 在客户端webView.getSet

Android开发之搜芽项目的图片加载问题(使用Volley进行网络图片加载)

搜芽的移动开发这几天进度相对来说非常的快.但是美中不足的就是网络图片的加载问题.我有两套方案: 1)沿用迅雷动漫的图片加载.迅雷动漫也是用的一个开源的库.但是不知道是我使用出了问题还是真的是它的问题.在我迅速的下拉和回倒的时候, 不确定的会出现崩溃.logcat显示loadImage里面出现了内存溢出.out of memory..这个我想应该不是我的问题. 2)采用外包的AsyncImageLoader.这个文件我没有仔细看.然后实验结果是,加载图片巨慢.而且容易导致卡顿. 所以,我将希望转向

三种基本网络加载图片方式

代码片段(6) [全屏查看所有代码] 1. [代码]普通加载网络方式     ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 public class NormalLoadPictrue {   

详谈高大上的图片加载框架Glide -源码篇

在上篇文章中,我们介绍了Glide图片加载框架的使用,通过之前的学习,我们可能已经能熟练的将Glide图片加载框架运用到我们的项目中,但是如果有人问你它是如何加载,工作原理是怎样的?为什么自定义GlideModule只需要在Manifest文件中加入meta-data即可?等等很多加载流程以及使用的注意事项.当然要想搞明白这些问题,就需要我们对Glide源码有个大致的认识,去剖析源码深处的奥秘. 接下来就让我们一起去进入Glide的源码世界,本篇文章分析的是Glide 3.7.0版本.特别提醒,

Android利用Volley异步加载数据(JSON和图片)完整示例

Android利用Volley异步加载数据(JSON和图片)完整示例 MainActivity.java package cc.testvolley; import org.json.JSONObject; import android.app.Activity; import android.app.ProgressDialog; import android.graphics.Bitmap; import android.os.Bundle; import android.support.v