0.调用:

  BaseAdapter中设置方法  holder.iv.loadImage(url);

  adapter_xxx.xml 中 控件需要用 xxx.NetWorkImageView

1 NetWorkImageView.java 和 异步加载图片的代码 AsyncImageLoader.java

import com.example.textimage.AsyncImageLoader.ImageLoadCallback;

import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView; /**
* 自定义加载网络图片ImageView
*
* @author mrljdx
* https://github.com/mrljdx/LoadImageView/tree/master/src/com/mrljdx
* /loadimage
*
*/
public class NetWorkImageView extends ImageView {
private final static String TAG = "NetWorkImageView";
private static AsyncImageLoader asyncImageLoader;
private Context context; public NetWorkImageView(Context context) {
this(context, null);
} public NetWorkImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public NetWorkImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initSth(context);
} private void initSth(Context context) {
this.context = context;
if (asyncImageLoader == null) {
asyncImageLoader = new AsyncImageLoader(context);
}
} public void loadImage(String imgUrl, final int defaultRes) {
if (TextUtils.isEmpty(imgUrl)) {
setImageResource(defaultRes);// 调用ImageView中默认的设置图片方法
return;
}
Log.d(TAG, "load imgUrl is :" + imgUrl);
Drawable d = asyncImageLoader.loadDrawable(imgUrl,
new ImageLoadCallback() { @Override
public void imageLoaded(Drawable drawable, String imgUrl) {
Object tag = getTag(); // 获取NetWorkImageView设置的Tag值,比对如果有则不再重新加载
if (tag != null && (tag instanceof String)
&& !tag.toString().equals(imgUrl)) {
return;
}
if (context instanceof Activity) { // 如果当前Activity被结束了,则不加载图片
if (((Activity) context).isFinishing()) {
return;
}
}
// 设置显示图片
setImage(drawable, defaultRes);
}
});
setImage(d, defaultRes);
} // 显示图片
private void setImage(Drawable drawable, int defaultRes) {
if (drawable != null) {
setImageDrawable(drawable);
return;
}
if (defaultRes != -1) {
setImageResource(defaultRes);
} } public void loadImage(String imgUrl) {
loadImage(imgUrl, -1);
} /**
* 取消加载图片
*/
public void cancelTask() {
asyncImageLoader.shutDownTread();
} }
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log; /**
* 异步网络请求图片加载类
*
* @author mrljdx
*
*/
public class AsyncImageLoader {
final static String TAG = "AsyncImageLoader";
/** /sdcard/Android/data/%package_name%/files/images */
private static File PIC_PATH; private static HashMap<String, SoftReference<Drawable>> picCache;
private BitmapFactory.Options opts = new BitmapFactory.Options();
private ExecutorService excutorsService = Executors.newFixedThreadPool(1);
private int width;
private int height;
private Context mContext; public AsyncImageLoader(Context context) {
this.mContext = context;
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
Log.d(TAG, "Max memory is " + maxMemory + "M"); PIC_PATH = new File(mContext.getExternalFilesDir("images")
+ File.separator); picCache = new HashMap<String, SoftReference<Drawable>>();
opts.inSampleSize = 1;
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
} public void setThreads(int num) {
this.excutorsService = Executors.newFixedThreadPool(num);
} public interface ImageLoadCallback {
public void imageLoaded(Drawable drawable, String imgUrl);
} // 加载图片
public Drawable loadDrawable(final String imgUrl,
final ImageLoadCallback mCallback) {
if (TextUtils.isEmpty(imgUrl)) {
return null;
}
// 获取图片文件名称
final String fileName = imgUrl.substring(imgUrl.lastIndexOf("/") + 1);
final String imgUrlHashCode = imgUrl.hashCode() + "";
// 如果有缓存则返回图片
if (picCache.containsKey(imgUrlHashCode)) {
Drawable imgDrawable = picCache.get(imgUrlHashCode).get();
if (imgDrawable != null) {
return imgDrawable;
}
}
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
mCallback.imageLoaded((Drawable) msg.obj, imgUrl);
}
};
excutorsService.submit(new Runnable() { @Override
public void run() {
Drawable drawable = loadImageFromUrl(imgUrl, fileName);
if (drawable != null) {// 获取到图片
if (width != 0) {
try {
drawable = zoomDrawable(drawable, width, height,
fileName);
} catch (Exception e) {
e.printStackTrace();
}
width = 0;
height = 0;
}
picCache.put(imgUrlHashCode, new SoftReference<Drawable>(
drawable));
}
handler.sendMessage(handler.obtainMessage(0, drawable));
}
});
return null;
} // 通过网络请求获取图片
public Drawable loadImageFromUrl(String imgUrl, String fileName) {
if (TextUtils.isEmpty(imgUrl)) {
return null;
}
Drawable drawable = null;
fileName = String.valueOf(fileName.hashCode()); // 将文件名hash
if (!PIC_PATH.exists()) {// 判断存放图片的文件夹是否存在
PIC_PATH.mkdirs();// 不存在则创建一个图片文件夹
}
File imgFile = new File(PIC_PATH, fileName);
if (imgFile.exists()) {// 如果存在在SD卡中,则返回SD卡里的图片
try {
drawable = getDrawableFromSdcard(fileName);
} catch (OutOfMemoryError outOfMemoryError) {
outOfMemoryError.printStackTrace();
return null;
}
return getDrawableFromSdcard(fileName);
} else {// 如果内存和SD卡都不存在则网络请求图片
URL url;
BufferedInputStream inputStream = null;
HttpURLConnection con = null;
try {
Log.d(TAG, "load imgUrl is:" + imgUrl);
url = new URL(imgUrl);
con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(15000);// 设置网络请求超时时间15秒
con.setReadTimeout(15000);
con.connect(); InputStream is = con.getInputStream(); // 获取图片流
inputStream = new BufferedInputStream(is); // 赋值
saveImage(imgFile, inputStream); // 保存图片到本地SD卡
is.close();// 关闭输入流 // String imgCookie = con.getHeaderField(pos); } catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} catch (MalformedURLException e1) {
e1.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (con != null) {
con.disconnect();
}
if (inputStream != null)
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} return drawable;
} // 从本地SD卡获取图片
private Drawable getDrawableFromSdcard(String fileName) { Bitmap source = BitmapFactory.decodeFile(PIC_PATH + File.separator
+ fileName, opts);
if (source == null) {
return null;
} else {
return new BitmapDrawable(source);
}
} // 保存图片到本地SD卡
private void saveImage(File image, BufferedInputStream bis) {
if (image != null && image.getParentFile() != null) {
image.getParentFile().mkdirs();
}
FileOutputStream fos = null; // 定义文件输出流
int BUFFER_SIZE = 1024;
byte[] buf = new byte[BUFFER_SIZE];
int size = 0;
try {
fos = new FileOutputStream(image);
while ((size = bis.read(buf)) != -1) {
fos.write(buf, 0, size);
}
;
fos.close();
bis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} // 取消所有正在执行的任务
public void shutDownTread() {
excutorsService.shutdownNow();
} // 处理图片
private Drawable zoomDrawable(Drawable drawable, int w, int h,
String fileName) {
// 取图片的真实大小
int intrinsicw = drawable.getIntrinsicWidth();
int intrinsich = drawable.getIntrinsicHeight();
// 设置为true,表示解析Bitmap对象,该对象不占内存
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(PIC_PATH + File.separator + fileName, opts); // 设置为false,解析Bitmap对象加入到内存中
opts.inJustDecodeBounds = false;
int width = opts.outWidth;
int height = opts.outHeight;
drawable.setBounds(0, 0, width, height); int minW = Math.min(width, w);
int minH = Math.min(height, h); float scaleWidth = ((float) w / intrinsicw);
float scaleHeight = ((float) h / intrinsich);
Matrix matrix = new Matrix();
if (minW == width && minH == height) {
scaleWidth = scaleHeight = mContext.getResources()
.getDisplayMetrics().density;
} else if (minW == width && minH == h) {
scaleWidth = scaleHeight;
} else if (minW == w && minH == height) {
scaleHeight = scaleWidth;
} else {
scaleWidth = scaleHeight = Math.min(scaleWidth, scaleHeight);
}
Bitmap oldbmp = drawableToBitmap(drawable, width, height);
matrix.postScale(scaleWidth, scaleHeight);
Bitmap newbmp = Bitmap.createBitmap(oldbmp, 0, 0, width, height,
matrix, true);
return new BitmapDrawable(null, newbmp);
} // Drawable To Bitmap
private Bitmap drawableToBitmap(Drawable drawable, int width, int height) {
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565;
Bitmap bitmap = Bitmap.createBitmap(width, height, config);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, width, height);
drawable.draw(canvas);
return bitmap;
}
}

android 自定义控件之NetWorkImageView 处理listview等控件中的图片加载乱序问题的更多相关文章

  1. Winform开发框架之客户关系管理系统(CRM)的开发总结系列4-Tab控件页面的动态加载

    在前面介绍的几篇关于CRM系统的开发随笔中,里面都整合了多个页面的功能,包括多文档界面,以及客户相关信息的页面展示,这个模块就是利用DevExpress控件的XtraTabPage控件的动态加载实现的 ...

  2. Android自定义控件View(三)组合控件

    不少人应该见过小米手机系统音量控制UI,一个圆形带动画效果的音量加减UI,效果很好看.它是怎么实现的呢?这篇博客来揭开它的神秘面纱.先上效果图 相信很多人都知道Android自定义控件的三种方式,An ...

  3. 控件WebView网页的加载

    Android:控件WebView网页的加载 WebView可以使得网页轻松的内嵌到app里,还可以直接跟js相互调用. webview有两个方法:setWebChromeClient 和 setWe ...

  4. 重新想象 Windows 8.1 Store Apps (81) - 控件增强: WebView 之加载本地 html, 智能替换 html 中的 url 引用, 通过 Share Contract 分享 WebView 中的内容, 为 WebView 截图

    [源码下载] 重新想象 Windows 8.1 Store Apps (81) - 控件增强: WebView 之加载本地 html, 智能替换 html 中的 url 引用, 通过 Share Co ...

  5. 在RichTextBox控件中插入图片

    . 在RichTextBox控件中插入图片 关键点 . 实现过程 .   public void ShowInsertImageDlg() {     OpenFileDialog OpenFileD ...

  6. 在RichTextBox控件中添加图片和文字

    public void SetText(RichTextBox rtb) { rtb.Text = "在RichTextBox控件中添加图片和文字" + Environment.N ...

  7. 背水一战 Windows 10 (64) - 控件(WebView): 加载指定 HttpMethod 的请求, 自定义请求的 http header, app 与 js 的交互

    [源码下载] 背水一战 Windows 10 (64) - 控件(WebView): 加载指定 HttpMethod 的请求, 自定义请求的 http header, app 与 js 的交互 作者: ...

  8. Android Handler 异步消息处理机制的妙用 创建强大的图片加载类(转)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38476887 ,本文出自[张鸿洋的博客] 最近创建了一个群,方便大家交流,群号: ...

  9. 一起来学习Android自定义控件2-简单的写字板控件

    概述 上一篇文章我们对自定义控件进行了一个大体的知识介绍.今天就来学习自定义一个简单的写字板控件. 先来看看效果图 就是简单的根据手指写下的轨迹去画出内容 实现 在上一篇文章里提到了android官方 ...

随机推荐

  1. 在Ubuntu上安装Qt5.2.0

    分类: QT2013-12-16 14:44 3171人阅读 评论(0) 收藏 举报 QT官方站点的文档有点老.今天,我尝试着在我的Ubuntu 13.10上安装Qt 5.2.0.下面是我的步骤: 1 ...

  2. 五子棋AI教程

    https://github.com/Chuck-Ai/gobang 我写了非常详细的中文教程,教你如何一步步编写自己的五子棋AI: 五子棋AI设计教程第二版一:前言 五子棋AI设计教程第二版二:博弈 ...

  3. Django中的 返回json对象的方式

    在返回json对象的几种方式: 1 from django.shortcuts import render, HttpResponse # Create your views here. from d ...

  4. IO调度 | Linux块设备中的IO路径及调度策略

    当文件系统通过submit_bio提交IO之后,请求就进入了通用块层.通用块层会对IO进行一些预处理的动作,其目的是为了保证请求能够更加合理的发送到底层的磁盘设备,尽量保证性能最佳.这里面比较重要的就 ...

  5. WPF 设置TextBox为空时,背景为文字提示。

    <TextBox FontSize="> <TextBox.Resources> <VisualBrush x:Key="HelpBrush" ...

  6. Build Telemetry for Distributed Services之OpenTracing项目

    中文文档地址:https://wu-sheng.gitbooks.io/opentracing-io/content/pages/quick-start.html 中文github地址:https:/ ...

  7. 图像分割-Mask Scoring R-CNN

    转载:https://zhuanlan.zhihu.com/p/58291808 论文链接:https://arxiv.org/abs/1903.00241 代码链接:https://github.c ...

  8. JS 事件介绍

    1.设置js对象属性为事件处理程序 事件处理程序属性的名字由“on”后面跟着事件名组成.这些属性名 都必须小写 事件处理程序的缺点:设计都是围绕着假设每个事件目标对于每种事件类型将最多只有一个处理程序 ...

  9. java处理jqueryGantt甘特图数据的task.depends依赖规则方法

    前端采用jqueryGantt,github地址为:https://github.com/robicch/jQueryGantt 原以为后端只需要简单地保存甘特图任务列表和返回任务列表就行了. 但功能 ...

  10. Flutter 状态管理 flutter_Provide

    项目的商品类别页面将大量的出现类和类中间的状态变化,这就需要状态管理.现在Flutter的状态管理方案很多,redux.bloc.state.Provide. Scoped Model : 最早的状态 ...