• ImageLoader


    原文地址https://github.com/singwhatiwanna/android-art-res/tree/master/Chapter_12/src/com/ryg/chapter_12/loader

    public class ImageLoader {
    
        private static final String TAG = "ImageLoader";
    
        public static final int MESSAGE_POST_RESULT = 1;
    
        private static final int CPU_COUNT = Runtime.getRuntime()
                .availableProcessors();
        private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
        private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
        private static final long KEEP_ALIVE = 10L;
    
        private static final int TAG_KEY_URI = R.id.imageloader_uri;
        private static final long DISK_CACHE_SIZE = 1024 * 1024 * 50;
        private static final int IO_BUFFER_SIZE = 8 * 1024;
        private static final int DISK_CACHE_INDEX = 0;
        private boolean mIsDiskLruCacheCreated = false;
    
        private static final ThreadFactory sThreadFactory = new ThreadFactory() {
            private final AtomicInteger mCount = new AtomicInteger(1);
    
            public Thread newThread(Runnable r) {
                return new Thread(r, "ImageLoader#" + mCount.getAndIncrement());
            }
        };
    
        public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE,
                KEEP_ALIVE, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(), sThreadFactory);
        
        private Handler mMainHandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                LoaderResult result = (LoaderResult) msg.obj;
                ImageView imageView = result.imageView;
                String uri = (String) imageView.getTag(TAG_KEY_URI);
                if (uri.equals(result.uri)) {
                    imageView.setImageBitmap(result.bitmap);
                } else {
                    Log.w(TAG, "set image bitmap,but url has changed, ignored!");
                }
            };
        };
    
        private Context mContext;
        private ImageResizer mImageResizer = new ImageResizer();
        private LruCache<String, Bitmap> mMemoryCache;
        private DiskLruCache mDiskLruCache;
    
        private ImageLoader(Context context) {
            mContext = context.getApplicationContext();
            int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
            int cacheSize = maxMemory / 8;
            mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
                @Override
                protected int sizeOf(String key, Bitmap bitmap) {
                    return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
                }
            };
            File diskCacheDir = getDiskCacheDir(mContext, "bitmap");
            if (!diskCacheDir.exists()) {
                diskCacheDir.mkdirs();
            }
            if (getUsableSpace(diskCacheDir) > DISK_CACHE_SIZE) {
                try {
                    mDiskLruCache = DiskLruCache.open(diskCacheDir, 1, 1,
                            DISK_CACHE_SIZE);
                    mIsDiskLruCacheCreated = true;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * build a new instance of ImageLoader
         * @param context
         * @return a new instance of ImageLoader
         */
        public static ImageLoader build(Context context) {
            return new ImageLoader(context);
        }
    
        private void addBitmapToMemoryCache(String key, Bitmap bitmap) {
            if (getBitmapFromMemCache(key) == null) {
                mMemoryCache.put(key, bitmap);
            }
        }
    
        private Bitmap getBitmapFromMemCache(String key) {
            return mMemoryCache.get(key);
        }
    
        /**
         * load bitmap from memory cache or disk cache or network async, then bind imageView and bitmap.
         * NOTE THAT: should run in UI Thread
         * @param uri http url
         * @param imageView bitmap's bind object
         */
        public void bindBitmap(final String uri, final ImageView imageView) {
            bindBitmap(uri, imageView, 0, 0);
        }
    
        public void bindBitmap(final String uri, final ImageView imageView,
                final int reqWidth, final int reqHeight) {
            imageView.setTag(TAG_KEY_URI, uri);
            Bitmap bitmap = loadBitmapFromMemCache(uri);
            if (bitmap != null) {
                imageView.setImageBitmap(bitmap);
                return;
            }
    
            Runnable loadBitmapTask = new Runnable() {
    
                @Override
                public void run() {
                    Bitmap bitmap = loadBitmap(uri, reqWidth, reqHeight);
                    if (bitmap != null) {
                        LoaderResult result = new LoaderResult(imageView, uri, bitmap);
                        mMainHandler.obtainMessage(MESSAGE_POST_RESULT, result).sendToTarget();
                    }
                }
            };
            THREAD_POOL_EXECUTOR.execute(loadBitmapTask);
        }
    
        /**
         * load bitmap from memory cache or disk cache or network.
         * @param uri http url
         * @param reqWidth the width ImageView desired
         * @param reqHeight the height ImageView desired
         * @return bitmap, maybe null.
         */
        public Bitmap loadBitmap(String uri, int reqWidth, int reqHeight) {
            Bitmap bitmap = loadBitmapFromMemCache(uri);
            if (bitmap != null) {
                Log.d(TAG, "loadBitmapFromMemCache,url:" + uri);
                return bitmap;
            }
    
            try {
                bitmap = loadBitmapFromDiskCache(uri, reqWidth, reqHeight);
                if (bitmap != null) {
                    Log.d(TAG, "loadBitmapFromDisk,url:" + uri);
                    return bitmap;
                }
                bitmap = loadBitmapFromHttp(uri, reqWidth, reqHeight);
                Log.d(TAG, "loadBitmapFromHttp,url:" + uri);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            if (bitmap == null && !mIsDiskLruCacheCreated) {
                Log.w(TAG, "encounter error, DiskLruCache is not created.");
                bitmap = downloadBitmapFromUrl(uri);
            }
    
            return bitmap;
        }
    
        private Bitmap loadBitmapFromMemCache(String url) {
            final String key = hashKeyFormUrl(url);
            Bitmap bitmap = getBitmapFromMemCache(key);
            return bitmap;
        }
    
        private Bitmap loadBitmapFromHttp(String url, int reqWidth, int reqHeight)
                throws IOException {
            if (Looper.myLooper() == Looper.getMainLooper()) {
                throw new RuntimeException("can not visit network from UI Thread.");
            }
            if (mDiskLruCache == null) {
                return null;
            }
            
            String key = hashKeyFormUrl(url);
            DiskLruCache.Editor editor = mDiskLruCache.edit(key);
            if (editor != null) {
                OutputStream outputStream = editor.newOutputStream(DISK_CACHE_INDEX);
                if (downloadUrlToStream(url, outputStream)) {
                    editor.commit();
                } else {
                    editor.abort();
                }
                mDiskLruCache.flush();
            }
            return loadBitmapFromDiskCache(url, reqWidth, reqHeight);
        }
    
        private Bitmap loadBitmapFromDiskCache(String url, int reqWidth,
                int reqHeight) throws IOException {
            if (Looper.myLooper() == Looper.getMainLooper()) {
                Log.w(TAG, "load bitmap from UI Thread, it's not recommended!");
            }
            if (mDiskLruCache == null) {
                return null;
            }
    
            Bitmap bitmap = null;
            String key = hashKeyFormUrl(url);
            DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);
            if (snapShot != null) {
                FileInputStream fileInputStream = (FileInputStream)snapShot.getInputStream(DISK_CACHE_INDEX);
                FileDescriptor fileDescriptor = fileInputStream.getFD();
                bitmap = mImageResizer.decodeSampledBitmapFromFileDescriptor(fileDescriptor,
                        reqWidth, reqHeight);
                if (bitmap != null) {
                    addBitmapToMemoryCache(key, bitmap);
                }
            }
    
            return bitmap;
        }
    
        public boolean downloadUrlToStream(String urlString,
                OutputStream outputStream) {
            HttpURLConnection urlConnection = null;
            BufferedOutputStream out = null;
            BufferedInputStream in = null;
    
            try {
                final URL url = new URL(urlString);
                urlConnection = (HttpURLConnection) url.openConnection();
                in = new BufferedInputStream(urlConnection.getInputStream(),
                        IO_BUFFER_SIZE);
                out = new BufferedOutputStream(outputStream, IO_BUFFER_SIZE);
    
                int b;
                while ((b = in.read()) != -1) {
                    out.write(b);
                }
                return true;
            } catch (IOException e) {
                Log.e(TAG, "downloadBitmap failed." + e);
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
                MyUtils.close(out);
                MyUtils.close(in);
            }
            return false;
        }
    
        private Bitmap downloadBitmapFromUrl(String urlString) {
            Bitmap bitmap = null;
            HttpURLConnection urlConnection = null;
            BufferedInputStream in = null;
    
            try {
                final URL url = new URL(urlString);
                urlConnection = (HttpURLConnection) url.openConnection();
                in = new BufferedInputStream(urlConnection.getInputStream(),
                        IO_BUFFER_SIZE);
                bitmap = BitmapFactory.decodeStream(in);
            } catch (final IOException e) {
                Log.e(TAG, "Error in downloadBitmap: " + e);
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
                MyUtils.close(in);
            }
            return bitmap;
        }
    
        private String hashKeyFormUrl(String url) {
            String cacheKey;
            try {
                final MessageDigest mDigest = MessageDigest.getInstance("MD5");
                mDigest.update(url.getBytes());
                cacheKey = bytesToHexString(mDigest.digest());
            } catch (NoSuchAlgorithmException e) {
                cacheKey = String.valueOf(url.hashCode());
            }
            return cacheKey;
        }
    
        private String bytesToHexString(byte[] bytes) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < bytes.length; i++) {
                String hex = Integer.toHexString(0xFF & bytes[i]);
                if (hex.length() == 1) {
                    sb.append('0');
                }
                sb.append(hex);
            }
            return sb.toString();
        }
    
        public File getDiskCacheDir(Context context, String uniqueName) {
            boolean externalStorageAvailable = Environment
                    .getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
            final String cachePath;
            if (externalStorageAvailable) {
                cachePath = context.getExternalCacheDir().getPath();
            } else {
                cachePath = context.getCacheDir().getPath();
            }
    
            return new File(cachePath + File.separator + uniqueName);
        }
    
        @TargetApi(VERSION_CODES.GINGERBREAD)
        private long getUsableSpace(File path) {
            if (Build.VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {
                return path.getUsableSpace();
            }
            final StatFs stats = new StatFs(path.getPath());
            return (long) stats.getBlockSize() * (long) stats.getAvailableBlocks();
        }
    
        private static class LoaderResult {
            public ImageView imageView;
            public String uri;
            public Bitmap bitmap;
    
            public LoaderResult(ImageView imageView, String uri, Bitmap bitmap) {
                this.imageView = imageView;
                this.uri = uri;
                this.bitmap = bitmap;
            }
        }
    }
  • 相关阅读:
    15回文相关问题
    14海量日志提取出现次数最多的IP
    13概率问题
    12胜者树和败者树

    pysnmp程序
    python 多线程 生产者消费者
    python多线程
    pysnmp使用
    PyYAML使用
  • 原文地址:https://www.cnblogs.com/anni-qianqian/p/8335981.html
Copyright © 2020-2023  润新知