zoukankan      html  css  js  c++  java
  • 解决ListView异步加载图片错乱问题 .

    发一个异步图片加载控件。网上也有大把的异步网络加载图片的控件,但是有一个问题,异步加载会造成列表中的图片混乱,因为列表的每一项的View都可能被重用,异步加载的时候多个异步线程引用到了同一个View将造成图片加载错乱。该控件解决这个问题:

    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.URL;
    import java.net.URLConnection;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.drawable.Drawable;
    import android.net.Uri;
    import android.os.AsyncTask;
    import android.util.AttributeSet;
    import android.widget.ImageView;
    
    /**
     * 异步图片控件
     * 使用:new AsyncImageView().asyncLoadBitmapFromUrl("http://xxxx","缓存路径"){
     *
     * @author gaoomei@gmail.com
     * @site http://obatu.sinaapp.com
     * @version 1.0
     * @2011-12-3
     */
    public class AsyncImageView extends ImageView {
    
        /**
         * 异步task加载器
         */
        private AsyncLoadImage mAsyncLoad;
    
        /**
         * 下载回来的图片缓存存活时间,单位:秒(s),默认30分钟
         */
        private long mCacheLiveTime = 1800;
    
        public AsyncImageView(Context context) {
            super(context);
        }
    
        public AsyncImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public AsyncImageView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        /**
         *
         */
        @Override
        public void setImageDrawable(Drawable drawable) {
            if (mAsyncLoad != null) {
                mAsyncLoad.cancel(true);
                mAsyncLoad = null;
            }
            super.setImageDrawable(drawable);
        }
    
        /**
         * 重写下面几个设置图片资源的方法,目地是取消网络加载
         */
        @Override
        public void setImageResource(int resId) {
            cancelLoad();
            super.setImageResource(resId);
        }
    
        @Override
        public void setImageURI(Uri uri) {
            cancelLoad();
            super.setImageURI(uri);
        }
    
        @Override
        public void setImageBitmap(Bitmap bitmap) {
            cancelLoad();
            super.setImageBitmap(bitmap);
        }
    
        /**
         * 取消正在进行的异步task
         */
        public void cancelLoad() {
            if (mAsyncLoad != null) {
                mAsyncLoad.cancel(true);
                mAsyncLoad = null;
            }
        }
    
        /**
         * 设置图片存活时间
         *
         * @param second
         *            存活时间,单位【秒】,如果等于0或null,则不缓存
         */
        public void setCacheLiveTime(long second) {
            if (second == 0) {
                this.mCacheLiveTime = 0;
            } else if (second >= 0) {
                this.mCacheLiveTime = second * 1000;
            }
        }
    
        /**
         * 从网络异步加载
         *
         * @param url
         * @param saveFileName
         */
        public void asyncLoadBitmapFromUrl(String url, String saveFileName) {
            if (mAsyncLoad != null) {
                mAsyncLoad.cancel(true);
            }
            // AsyncTask不可重用,所以每次重新实例
            mAsyncLoad = new AsyncLoadImage();
            mAsyncLoad.execute(url, saveFileName);
        }
    
        /**
         * 异步加载器
         */
        private class AsyncLoadImage extends AsyncTask {
            /**
             * 是否取消
             */
            private boolean isCancel = false;
    
            @Override
            protected Bitmap doInBackground(String... params) {
                if (isCancel) {
                    return null;
                }
                String url = params[0];
                String fileName = params[1];
                try {
                    return getBitmap(url, fileName);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }
    
            @Override
            protected void onCancelled() {
                System.out.println("async load imgae cancel");
                isCancel = true;
            }
    
            @Override
            protected void onPostExecute(Bitmap result) {
                if (!isCancel && result != null) {
                    AsyncImageView.this.setImageBitmap(result);
                }
            }
        }
    
        /**
         * 下载图片
         *
         * @param urlString
         *            url下载地址
         * @param fileName
         *            缓存文件路径
         * @throws IOException
         */
        private Bitmap getBitmap(String urlString, String fileName)
                throws IOException {
            if (fileName == null || fileName.trim().isEmpty()) {
                InputStream input = getBitmapInputStreamFromUrl(urlString);
                return BitmapFactory.decodeStream(input);
            }
    
            File file = new File(fileName);
            if (!file.isFile()
                    || (mCacheLiveTime > 0 && (System.currentTimeMillis()
                            - file.lastModified() > mCacheLiveTime))) {
                InputStream input = getBitmapInputStreamFromUrl(urlString);
                file = saveImage(input, fileName);
                // 如果文件结构创建失败,则直接从输入流解码图片
                if (file == null || !file.exists() || !file.canWrite()
                        || !file.canRead()) {
                    return BitmapFactory.decodeStream(input);
                }
            }
            return BitmapFactory.decodeFile(file.getAbsolutePath());
        }
    
        /**
         * 下载图片,输入InputStream
         *
         * @param urlString
         * @return
         * @throws IOException
         */
        private InputStream getBitmapInputStreamFromUrl(String urlString)
                throws IOException {
            URL url = new URL(urlString);
            URLConnection connection = url.openConnection();
            connection.setConnectTimeout(25000);
            connection.setReadTimeout(90000);
            return connection.getInputStream();
        }
    
        /**
         * 从输入流保存图片到文件系统
         *
         * @param fileName
         * @param input
         * @return
         */
        private File saveImage(InputStream input, String fileName) {
            if (fileName.trim().isEmpty() || input == null) {
                return null;
            }
            File file = new File(fileName);
            OutputStream output = null;
            try {
                file.getParentFile().mkdirs();
                if (file.exists() && file.isFile()) {
                    file.delete();
                }
                if (!file.createNewFile()) {
                    return null;
                }
                output = new FileOutputStream(file);
                byte[] buffer = new byte[4 * 1024];
                do {
                    // 循环读取
                    int numread = input.read(buffer);
                    if (numread == -1) {
                        break;
                    }
                    output.write(buffer, 0, numread);
                } while (true);
                output.flush();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
            return file;
        }
    }
  • 相关阅读:
    一些常用的代码规范
    策略模式学习,使用go实现策略模式
    数据库作业3:第二章课后题
    数据库作业4:SQL练习1
    对数据库相关的概念自己的理解
    SQL server的初步使用
    对于高德地图SDK的开发使用
    滑稽(好像会动)!
    羊车门作业
    对Python课的看法
  • 原文地址:https://www.cnblogs.com/vip-ygh/p/3569606.html
Copyright © 2011-2022 走看看