DiskLruCache和Lrucache缓存bitmap

三级缓存,先在内存Lrucache中查找缓存,没有就去外存DiskLrucache中查找,再没有就下载,Lru不会自动删除,所以要设置最大缓存内存,后台运行Lrucache不会消失,关闭程序Disklrucache不会消失.代码有点乱,但还是可以用的

public class MainActivity extends AppCompatActivity {
    private GridView gv_photo;
    PhotoWall photoWall;
    ImageView imageView;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = findViewById(R.id.image);
        photoWall = new PhotoWall();
    }

            @Override
            protected void onPause() {
                super.onPause();
                photoWall.flushCache();
            }

            @Override
            protected void onDestroy() {
                super.onDestroy();
               photoWall.cancelTask();
            }

    @Override
    protected void onStart() {
        super.onStart();
        photoWall.getView();
    }

    public  class PhotoWall {

        // 声明LruCache缓存对象
        private LruCache<String, Bitmap> lruCache;
        // 声明DiskLruCache硬盘缓存对象
        private DiskLruCache diskLruCache;
        // 任务队列
        private Set<LoadImageAsync> tasks;
        // 声明GridView对象
        private GridView gridView;
        ImageView imageView;

        public PhotoWall() {

            this.gridView = gridView;
            tasks = new HashSet<LoadImageAsync>();
            /**
             * 初始化内存缓存LruCache
             */
            // 获取应用程序最大可占内存值
            int maxMemory = (int) Runtime.getRuntime().maxMemory();
            // 设置最大内存的八分之一作为缓存大小
            int lruMemory = maxMemory / 8;
            lruCache = new LruCache<String, Bitmap>(lruMemory) {
                @Override
                protected int sizeOf(String key, Bitmap bitmap) {
                    // 返回Bitmap对象所占大小,单位:kb
                    return bitmap.getByteCount();
                }

            };
            /**
             * 初始化硬盘缓存DiskLruCahce
             */
            // 获取硬盘缓存路径,参数二为所在缓存路径的文件夹名称
            File directory = getDiskCacheDir(getApplicationContext(), "aaa");

            if (!directory.exists()) {
                // 若文件夹不存在,建立文件夹
                directory.mkdirs();
            }
            int appVersion = getAppVersion(getApplicationContext());
            try {
                // 参数1:缓存文件路径,参数2:系统版本号,参数3:一个缓存路径对于几个文件,参数4:缓存空间大小:字节
                diskLruCache = DiskLruCache.open(directory, appVersion, 1, 1024 * 1024 * 10);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

        /**
         * @param context
         * @param uniqueName
         * @return
         *         当SD卡存在或者SD卡不可被移除的时候,就调用getExternalCacheDir()方法来获取缓存路径,否则就调用getCacheDir
         *         ()方法来获取缓存路径。 前者获取到的就是 /sdcard/Android/data/<application
         *         package>/cache 这个路径 而后者获取到的是 datadata/application package>/cache
         *         这个路径。
         */
        public File getDiskCacheDir(Context context, String uniqueName) {
            String cachePath;
            if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable()) {
                cachePath = context.getExternalCacheDir().getPath();
            } else {
                cachePath = context.getCacheDir().getPath();
            }
            return new File(cachePath + File.separator + uniqueName);
        }

        /**
         * @param context
         * @return 获取系统版本号
         */
        public int getAppVersion(Context context) {
            try {
                PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
                return info.versionCode;
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
            return 1;
        }

        public View getView() {
            // 获取图片资源URL地址
            String path ="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=2548029202,3494755824&fm=27&gp=0.jpg";
            // 获取控件实例
             imageView = findViewById(R.id.image);
            // 设置一个唯一标识符,避免异步加载图片时错位
//            imageView.setTag(path);
            // 设置默认图片
            imageView.setImageResource(R.drawable.icon12);
            // 根据图片URL到缓存中去找图片资源并设置
            setImageFromLruCache(path, imageView);
            return imageView;
        }

        /**
         * 根据图片URL地址获取缓存中图片,若不存在去磁盘缓存中查找=》网络下载
         *
         * @param path
         * @param imageView
         */
        private void setImageFromLruCache(String path, ImageView imageView) {
            Bitmap bitmap = lruCache.get(path);
            if (bitmap != null) {
                // 缓存存在,取出设置图片
                Log.i("PhotoWallAdapter", "在内存缓存中找到");
                imageView.setImageBitmap(bitmap);
            } else {
                // 缓存不存在,先找硬盘缓存,还不存在,就去网络下载(开启异步任务)
                LoadImageAsync loadImageAsync = new LoadImageAsync();
                loadImageAsync.execute(path);
                // 添加任务到任务队列
                tasks.add(loadImageAsync);
            }
        }

        /**
         * 取消队列中准备下载和正在下载的任务
         */
        public void cancelTask() {
            for (LoadImageAsync task : tasks) {
                task.cancel(false);
            }
        }

        /**
         * 同步内存操作到journal文件
         */
        public void flushCache() {
            if (diskLruCache != null) {
                try {
                    diskLruCache.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

        class LoadImageAsync extends AsyncTask<String, Void, Bitmap> {
            // 图片资源URL
            String path = null;

            @Override
            protected Bitmap doInBackground(String... params) {
                // 图片下载地址
                this.path = params[0];
                DiskLruCache.Snapshot snapshot = null;
                OutputStream outputStream = null;
                Bitmap bitmap = null;
//                String pathMd5 = MD5Utils.md5(path);
                String key = hashKeyForDisk(path);
                // 根据图片url(md5)查找图片资源是否存在于硬盘缓存
                try {
                    snapshot = diskLruCache.get(key);
                    if (snapshot == null) {
                        // 在磁盘缓存中没有找到图片资源
                        // 获取一个DiskLruCache写入对象
                        DiskLruCache.Editor editor = diskLruCache.edit(key);
                        if (editor != null) {
                            outputStream = editor.newOutputStream(0);
                            // 开启异步网络任务获取图片,并存入磁盘缓存
                            if (downloadUrlToStream(path, outputStream)) {
                                // 下载成功
                                Log.i("PhotoWallAdapter", "下载文件成功");
                                editor.commit();
                            } else {
                                editor.abort();
                            }
                        }
                    }
                    // 图片写入磁盘缓存后,再一次的查找磁盘缓存
                    snapshot = diskLruCache.get(key);
                    if (snapshot != null) {
                        // 若查找到,获取图片,并把图片资源写入内存缓存
                        bitmap = BitmapFactory.decodeStream(snapshot.getInputStream(0));
                        Log.i("PhotoWallAdapter", "在磁盘缓存中找到");
                    }
                    if (bitmap != null) {
                        // 将Bitmap对象添加到内存缓存当中
                        lruCache.put(path, bitmap);
                    }
                    return bitmap;
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (outputStream != null) {
                        try {
                            outputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
                return null;
            }

            @Override
            protected void onPostExecute(Bitmap bitmap) {
                super.onPostExecute(bitmap);
                // 根据Tag获取控件对象并设置图片
//                ImageView imageView = (ImageView) gridView.findViewWithTag(path);
                if (imageView != null && bitmap != null) {
                    // 加载图片
                    imageView.setImageBitmap(bitmap);
                }
                tasks.remove(this);

            }

            /**
             * 根据图片URL地址下载图片,成功返回true,失败false
             *
             * @param urlString
             * @param outputStream
             * @return
             */
            private 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(), 8 * 1024);
                    out = new BufferedOutputStream(outputStream, 8 * 1024);
                    int b;
                    while ((b = in.read()) != -1) {
                        out.write(b);
                    }
                    return true;
                } catch (final IOException e) {
                    e.printStackTrace();
                } finally {
                    if (urlConnection != null) {
                        urlConnection.disconnect();
                    }
                    try {
                        if (out != null) {
                            out.close();
                        }
                        if (in != null) {
                            in.close();
                        }
                    } catch (final IOException e) {
                        e.printStackTrace();
                    }
                }
                return false;
            }

        }
        public  String hashKeyForDisk(String key) {
            String cacheKey;
            try {
                final MessageDigest mDigest = MessageDigest.getInstance("MD5");//把uri编译为MD5,防止网址有非法字符
                mDigest.update(key.getBytes());
                cacheKey = bytesToHexString(mDigest.digest());
            } catch (NoSuchAlgorithmException e) {
                cacheKey = String.valueOf(key.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();
        }
    }
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:id="@+id/line1"
    android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
    android:id="@+id/image"
    android:layout_width="match_parent"
    android:layout_height="200dp" />
</LinearLayout>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:hardwareAccelerated="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

猜你喜欢

转载自www.cnblogs.com/Ocean123123/p/10984236.html