• 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;
        }
    }
  • 相关阅读:
    JOINTJs笔记-5 实现节点的自动布局
    实现蛇形节点布局
    jointjs笔记4- 设置线的label,
    vue-图片src路径不存在时,显示默认图片
    vue-codemirror-merge插件的使用
    谷歌点击下载链接,闪了一下没有下载
    几个常用的正则
    vue 组件中再套用组件的情况,子组件中获取不到数据
    element-ui 组件常见错误 confirm, 分页的切换页码改变,表格样式错位
    Vue学习之路---No.7(分享心得,欢迎批评指正)
  • 原文地址:https://www.cnblogs.com/Westfalen/p/6738663.html
Copyright © 2020-2023  润新知