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