当前位置: 首页 > news >正文

android 自定义控件之NetWorkImageView 处理listview等控件中的图片加载乱序问题

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;
    }
}

 

转载于:https://www.cnblogs.com/Westfalen/p/6738663.html

相关文章:

  • Linux下搭建SVN服务器--基于LAMP
  • PHP中文件操作(1)--打开/读取文件
  • firewalld防火墙的配置及应用
  • Angular 4.x 动态创建组件
  • WEB架构想法考虑
  • gaojingsong----大数据博客
  • RDD原文翻译[转]
  • Scrum角色划分——绿唤
  • Codeforces Round #410 (Div. 2) 题解 【ABCD】
  • 《Java程序员面试秘笈》—— 面试题3 Linux操作系统下如何安装Java SE开发环境
  • 《好学的C++程序设计》——2.3 循址访问是怎样的
  • 《Adobe Fireworks CS5中文版经典教程》——1.5 使用多个文档
  • 《Android 应用案例开发大全(第3版)》——第2.6节绘制相关类
  • 《编写高质量代码:改善c程序代码的125个建议》——建议14-4:尽量避免在同一个数据上执行位操作与算术运算...
  • 《51单片机应用开发范例大全(第3版)》——1.4 【实例19】P1口控制直流电动机实例...
  • 「面试题」如何实现一个圣杯布局?
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • 10个最佳ES6特性 ES7与ES8的特性
  • input实现文字超出省略号功能
  • Javascript设计模式学习之Observer(观察者)模式
  • python 学习笔记 - Queue Pipes,进程间通讯
  • select2 取值 遍历 设置默认值
  • sessionStorage和localStorage
  • socket.io+express实现聊天室的思考(三)
  • ⭐ Unity 开发bug —— 打包后shader失效或者bug (我这里用Shader做两张图片的合并发现了问题)
  • vue-cli在webpack的配置文件探究
  • vue脚手架vue-cli
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • 百度地图API标注+时间轴组件
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • ------- 计算机网络基础
  • 聊聊flink的TableFactory
  • 如何合理的规划jvm性能调优
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • ​Python 3 新特性:类型注解
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • #vue3 实现前端下载excel文件模板功能
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (007)XHTML文档之标题——h1~h6
  • (4)事件处理——(7)简单事件(Simple events)
  • (LeetCode 49)Anagrams
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (第27天)Oracle 数据泵转换分区表
  • (附源码)php新闻发布平台 毕业设计 141646
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (十三)Flask之特殊装饰器详解
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转)四层和七层负载均衡的区别
  • ******IT公司面试题汇总+优秀技术博客汇总