Cache, L3 cache, memory overflow, AsyncTask

SharePreference tool class

/**
 * SharePreference encapsulation
 *
 */
public class PrefUtils {
    public static final String PREF_NAME = "config";
    public static boolean getBoolean(Context ctx, String key,
            boolean defaultValue) {
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        return sp.getBoolean(key, defaultValue);
    }
    public static void setBoolean(Context ctx, String key, boolean value) {
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        sp.edit().putBoolean(key, value).commit();
    }
    public static String getString(Context ctx, String key, String defaultValue) {
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        return sp.getString(key, defaultValue);
    }
    public static void setString(Context ctx, String key, String value) {
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        sp.edit().putString(key, value).commit();
    }
}

Cache tool class

public class CacheUtils {
    /**
     * Cache principle: set cache key as URL and value as json (parsed)
     */
    public static void setCache(String key, String value, Context ctx) {
        PrefUtils.setString(ctx, key, value);
        // You can put the cache in a file, the file name is Md5(url), and the file content is json
    }
    /**
     * Get cache key url
     */
    public static String getCache(String key, Context ctx) {
        return PrefUtils.getString(ctx, key, null);
    }
}

Usage:

1. After requesting the network, get the json data and save it

private void getDataFromServer() {
        HttpUtils utils = new HttpUtils();
        utils.send(HttpMethod.GET, GlobalContants.PHOTOS_URL,
                new RequestCallBack<String>() {
                    @Override
                    public void onSuccess(ResponseInfo<String> responseInfo) {
                        String result = (String) responseInfo.result;
                        parseData(result);
                        // Set cache
                        CacheUtils.setCache(GlobalContants.PHOTOS_URL, result,
                                mActivity);
                    }
                    @Override
                    public void onFailure(HttpException error, String msg) {
                        Toast.makeText(mActivity, msg, Toast.LENGTH_SHORT)
                                .show();
                        error.printStackTrace();
                    }
                });
    }
public void initData() {
    String cache = CacheUtils
            .getCache(GlobalContants.PHOTOS_URL, mActivity);
    if (!TextUtils.isEmpty(cache)) {
     // parseData(cache);
    }
    getDataFromServer();
}
protected void parseData(String result) {
        Gson gson = new Gson();
        PhotosData data = gson.fromJson(result, PhotosData.class);
        mPhotoList = data.data.news;// Get group diagram list collection
        if (mPhotoList != null) {
            mAdapter = new PhotoAdapter();
            lvPhoto.setAdapter(mAdapter);
            gvPhoto.setAdapter(mAdapter);
        }
    }

L3 cache

-Memory cache, priority loading, fastest speed -Local cache, second priority loading, fast speed -Network cache, no priority loading, slow speed, waste traffic

The image downloaded by the server uses the Http caching mechanism. The time of each execution sends the local image to the server. If the return code is 304, it indicates that the image on the server is the same as the local image. The locally saved image is directly used. If the return code is 200, start downloading new images and caching. After getting the picture from the server, you need to save one copy in the local and memory respectively, so that you can get it directly from the memory next time, which speeds up the display speed and improves the user experience.

Memory overflow OOM

The main reason for the memory leak is that the memory space was previously applied for and forgot to release. If there are references to useless objects in the program, these objects will reside in memory and consume memory, because the garbage collector GC cannot verify that these objects are no longer needed. If there is a reference to an object, the object is defined as a "valid activity" and will not be released. To make sure that the memory occupied by the object will be recycled, we must make sure that the object will no longer be used. A typical approach is to set the object data member to null or remove the object from the collection. However, when local variables are not needed, they do not need to be explicitly set to null, because these references will be automatically cleaned up when a method is executed

Out of memory (oom) means that the program does not have enough memory space for its use when applying for memory, resulting in out of memory; For example, if you apply for an integer, but save it with a long to save the number, that is, memory overflow.

Memory leak refers to that the program cannot release the applied memory space after applying for memory. The harm of a memory leak can be ignored, but the consequences of memory leak accumulation are very serious. No matter how much memory is, it will be occupied sooner or later. Memory leak will eventually lead to out of memory!

Solution 1: references in java (use soft references)

- the strong reference garbage collector will not recycle. java references are strong references by default - soft reference SoftReference: when the memory is insufficient, the garbage collector will consider recycling - weak reference WeakReference: when memory is insufficient, garbage collector will recycle preferentially - virtual reference PhantomReference. When memory is insufficient, garbage collector takes priority to recycle Note: Android 2 3 +, the system will recycle SoftReference objects in advance, even if there is enough memory

Solution 2: LruCache Least recently used algorithm The memory will be controlled within a certain size. When it exceeds the maximum value, it will be recycled automatically. The maximum value is set by the developer Solution 3: image compression

This is the principle of xutils. Now you don't need xutils. Now you can customize several tool classes

1. Custom loading tool class

public class MyBitmapUtils {
    NetCacheUtils mNetCacheUtils;
    LocalCacheUtils mLocalCacheUtils;
    MemoryCacheUtils mMemoryCacheUtils;
    public MyBitmapUtils() {
        mMemoryCacheUtils = new MemoryCacheUtils();
        mLocalCacheUtils = new LocalCacheUtils();
        mNetCacheUtils = new NetCacheUtils(mLocalCacheUtils, mMemoryCacheUtils);
    }
    public void display(ImageView ivPic, String url) {
        ivPic.setImageResource(R.drawable.news_pic_default);// Set default load picture
        Bitmap bitmap = null;
        // Read from memory
        bitmap = mMemoryCacheUtils.getBitmapFromMemory(url);
        if (bitmap != null) {
            ivPic.setImageBitmap(bitmap);
            System.out.println("Read pictures from memory...");
            return;
        }
        // Read from local
        bitmap = mLocalCacheUtils.getBitmapFromLocal(url);
        if (bitmap != null) {
            ivPic.setImageBitmap(bitmap);
            System.out.println("Read pictures locally...");
            mMemoryCacheUtils.setBitmapToMemory(url, bitmap);// Save pictures in memory
            return;
        }
        // Read from the network
        mNetCacheUtils.getBitmapFromNet(ivPic, url);
    }
}

2. Network cache and AsyncTask

public class NetCacheUtils {
    private LocalCacheUtils mLocalCacheUtils;
    private MemoryCacheUtils mMemoryCacheUtils;
    public NetCacheUtils(LocalCacheUtils localCacheUtils,
            MemoryCacheUtils memoryCacheUtils) {
        mLocalCacheUtils = localCacheUtils;
        mMemoryCacheUtils = memoryCacheUtils;
    }
    /**
     * Download pictures from the network
     *
     * @param ivPic
     * @param url
     */
    public void getBitmapFromNet(ImageView ivPic, String url) {
        new BitmapTask().execute(ivPic, url);// Start AsyncTask,
                                                // Parameters are obtained in doInbackground
    }
    /**
     * Handler Encapsulation of thread pool
     *
     * The first generic type: parameter type, the second generic type: the generic type of update progress, and the third generic type is the return result of onPostExecute
     *
     * @author Kevin
     *
     */
    class BitmapTask extends AsyncTask<Object, Void, Bitmap> {
        private ImageView ivPic;
        private String url;
        /**
         * The background time-consuming method is executed here, and the child thread
         */
        @Override
        protected Bitmap doInBackground(Object... params) {
            ivPic = (ImageView) params[0];
            url = (String) params[1];
            ivPic.setTag(url);// Bind url to imageview
            return downloadBitmap(url);
        }
        /**
         * Update progress, main thread
         */
        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
        }
        /**
         * After the time-consuming method ends, execute the method and the main thread
         */
        @Override
        protected void onPostExecute(Bitmap result) {
            if (result != null) {
                String bindUrl = (String) ivPic.getTag();
                if (url.equals(bindUrl)) {// Make sure the picture is set to the correct imageview
                    ivPic.setImageBitmap(result);
                    mLocalCacheUtils.setBitmapToLocal(url, result);// Save pictures locally
                    mMemoryCacheUtils.setBitmapToMemory(url, result);// Save pictures in memory
                    System.out.println("Read pictures from the network cache...");
                }
            }
        }
    }
    /**
     * Download pictures
     *
     * @param url
     * @return
     */
    private Bitmap downloadBitmap(String url) {
        HttpURLConnection conn = null;
        try {
            conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            conn.setRequestMethod("GET");
            conn.connect();
            int responseCode = conn.getResponseCode();
            if (responseCode == 200) {
                InputStream inputStream = conn.getInputStream();
                 
                //Image compression processing
                BitmapFactory.Options option = new BitmapFactory.Options();
                option.inSampleSize = 2;//The width and height are compressed to half of the original. This parameter needs to be determined according to the size of the picture to be displayed
                option.inPreferredConfig = Bitmap.Config.RGB_565;//Format picture
                 
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, option);
                return bitmap;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            conn.disconnect();
        }
        return null;
    }
}

3. The local cache (SD card) generally encrypts the file name with MD5

public class LocalCacheUtils {
    public static final String CACHE_PATH = Environment
            .getExternalStorageDirectory().getAbsolutePath() + "/zhbj_cache_52";
    /**
     * Read pictures from local sdcard
     */
    public Bitmap getBitmapFromLocal(String url) {
        try {
            String fileName = MD5Encoder.encode(url);
            File file = new File(CACHE_PATH, fileName);
            if (file.exists()) {
                Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(
                        file));//decodeStream is the input / output stream
                return bitmap;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * Write pictures to sdcard
     *
     * @param url
     * @param bitmap
     */
    public void setBitmapToLocal(String url, Bitmap bitmap) {
        try {
            String fileName = MD5Encoder.encode(url);
            File file = new File(CACHE_PATH, fileName);
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {// If the folder does not exist, create a folder
                parentFile.mkdirs();
            }
            // Save pictures locally
            bitmap.compress(CompressFormat.JPEG, 100,
                    new FileOutputStream(file));//100 is the quality
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

3. Memory cache:

Using LRUCache in memory is the most appropriate. If you use HashMap to implement it, it is not impossible, but you should pay attention to releasing the cache at an appropriate time. I haven't considered how to release it, but the problem with soft reference is that it's difficult for you to control the size of the cache, that is, your picture cache will not be recycled until your memory is about to burst. Does it feel silly?

public class MemoryCacheUtils {
    // private HashMap<String, SoftReference<Bitmap>> mMemoryCache = new
    // HashMap<String, SoftReference<Bitmap>>();// Start with a map and then use soft references
    private LruCache<String, Bitmap> mMemoryCache;
    public MemoryCacheUtils() {
        long maxMemory = Runtime.getRuntime().maxMemory() / 8;//The mainstream is 8 / 1 of 16m
        mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                int byteCount = value.getRowBytes() * value.getHeight();// Get the memory size occupied by the picture
                return byteCount;
            }
        };
    }
    /**
     * Read from memory
     *
     * @param url
     */
    public Bitmap getBitmapFromMemory(String url) {
        // SoftReference<Bitmap> softReference = mMemoryCache.get(url);
        // if (softReference != null) {
        // Bitmap bitmap = softReference.get();
        // return bitmap;
        // }
        return mMemoryCache.get(url);
    }
    /**
     * Write memory
     *
     * @param url
     * @param bitmap
     */
    public void setBitmapToMemory(String url, Bitmap bitmap) {
        // SoftReference<Bitmap> softReference = new
        // SoftReference<Bitmap>(bitmap);
        // mMemoryCache.put(url, softReference);
        mMemoryCache.put(url, bitmap);
    }
}

Added by smudge on Wed, 12 Jan 2022 11:44:35 +0200