SoFunction
Updated on 2025-03-04

Detailed explanation of Android pictures' level three cache and image compression

Why do I need image cache

By default, Android only allocates 16M of memory to each application, so if too many pictures are loaded, the pictures should be cached to prevent memory overflow. The third-level cache of the picture is:

  • Memory cache
  • Local cache
  • Network Cache

Among them, the memory cache should be loaded first, which is the fastest; the local cache should be loaded first, which is also fast; the network cache should not be loaded first, which is slow and consumes traffic.

Specific implementation of Level 3 cache

Network Cache

  • Load the picture according to the url of the picture
  • Cache locally and in memory

  

 public class NetCacheUtils {

    private LocalCacheUtils mLocalCacheUtils;
    private MemoryCacheUtils mMemoryCacheUtils;

    public NetCacheUtils(LocalCacheUtils localCacheUtils,
        MemoryCacheUtils memoryCacheUtils) {
      mLocalCacheUtils = localCacheUtils;
      mMemoryCacheUtils = memoryCacheUtils;
    }

    /**
      * Download pictures from the Internet
      *
      * @param ivPic
      * @param url
      */
    public void getBitmapFromNet(ImageView ivPic, String url) {
      new BitmapTask().execute(ivPic, url);// Start AsyncTask,                          // The parameters will be obtained in doInbackground    }

    /**
      * Encapsulation of Handler and thread pool
      *
      * The first generic: parameter type The second generic: the generic of the update progress, the third generic is the result of onPostExecute
      *
      *
      */
    class BitmapTask extends AsyncTask<Object, Void, Bitmap> {

      private ImageView ivPic;
      private String url;

      /**
        * The background time-consuming method is executed here, the child thread
        */
      @Override
      protected Bitmap doInBackground(Object... params) {
        ivPic = (ImageView) params[0];
        url = (String) params[1];

        (url);//Bind url and imageview
        return downloadBitmap(url);
      }

      /**
        * Update progress, main thread
        */
      @Override
      protected void onProgressUpdate(Void... values) {
        (values);
      }

      /**
        * After the time-consuming method is finished, execute the method, the main thread
        */
      @Override
      protected void onPostExecute(Bitmap result) {
        if (result != null) {
          String bindUrl = (String) ();

          if ((bindUrl)) {// Make sure the image settings are given the correct imageview            (result);
            (url, result);// Save the image locally            (url, result);// Save the image in memory            ("Read pictures from network cache...");
          }
        }
      }
    }

    /**
      * Download the picture
      *
      * @param url
      * @return
      */
    private Bitmap downloadBitmap(String url) {

      HttpURLConnection conn = null;
      try {
        conn = (HttpURLConnection) new URL(url).openConnection();

        (5000);
        (5000);
        ("GET");
        ();

        int responseCode = ();
        if (responseCode == 200) {
          InputStream inputStream = ();

          //Picture compression processing           option = new ();
           = 2;//The width and height are compressed to half of the original. This parameter needs to be determined based on the size of the picture to be displayed.           = .RGB_565;//Set picture format
          Bitmap bitmap = (inputStream, null, option);
          return bitmap;
        }

      } catch (Exception e) {
        ();
      } finally {
        ();
      }

      return null;
    }
  }

Local cache

Two methods: set local cache and get local cache

  public class LocalCacheUtils {

    public static final String CACHE_PATH = Environment
        .getExternalStorageDirectory().getAbsolutePath() + "/local_cache";

    /**
      * Read pictures from local sdcard
      */
    public Bitmap getBitmapFromLocal(String url) {
      try {
        String fileName = (url);
        File file = new File(CACHE_PATH, fileName);

        if (()) {
          Bitmap bitmap = (new FileInputStream(
              file));
          return bitmap;
        }

      } catch (Exception e) {
        ();
      }

      return null;
    }

    /**
      * Write pictures to SDcard
      *
      * @param url
      * @param bitmap
      */
    public void setBitmapToLocal(String url, Bitmap bitmap) {
      try {
        String fileName = (url);

        File file = new File(CACHE_PATH, fileName);

        File parentFile = ();
        if (!()) {// If the folder does not exist, create a folder          ();
        }

        // Save the image locally        (, 100,
            new FileOutputStream(file));
      } catch (Exception e) {
        ();
      }

    }
  }

Memory cache

Two methods: set the memory cache and obtain the memory cache

question:

If you use HashMap to store images, it will cause memory overflow when there are more and more pictures, because it is a strong reference, and Java's garbage collector will not recycle it.

If it is changed to a soft reference SoftReference (the garbage collector will consider recycling when the memory is insufficient), there is still a problem: in android 2.3+, the system will prioritize the SoftReference object in advance, even if the memory is sufficient.

Solution: LruCache can be used to solve the above-mentioned problem of not recycling or early recycling. least recently use The algorithm that will control the memory to a certain size and will automatically recycle it when it exceeds the maximum value. The developer will set this maximum value by himself.
 

    public class MemoryCacheUtils {

      // private HashMap<String, SoftReference<Bitmap>> mMemoryCache = new
      // HashMap<String, SoftReference<Bitmap>>();
      private LruCache<String, Bitmap> mMemoryCache;

      public MemoryCacheUtils() {
        long maxMemory = ().maxMemory() / 8;// The default emulator is 16M        mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {
          @Override
          protected int sizeOf(String key, Bitmap value) {
            int byteCount = () * ();// Get the memory size of the image            return byteCount;
          }
        };
      }

      /**
        * Read from memory
        *
        * @param url
        */
      public Bitmap getBitmapFromMemory(String url) {
        // SoftReference<Bitmap> softReference = (url);
        // if (softReference != null) {
        // Bitmap bitmap = ();
        // return bitmap;
        // }
        return (url);
      }

      /**
        * Write memory
        *
        * @param url
        * @param bitmap
        */
      public void setBitmapToMemory(String url, Bitmap bitmap) {
        // SoftReference<Bitmap> softReference = new
        // SoftReference<Bitmap>(bitmap);
        // (url, softReference);
        (url, bitmap);
      }
    }

Image compression

  //Image compression processing (compression is performed when obtaining pictures from the network)   option = new ();
   = 2;//The width and height are compressed to half of the original. This parameter needs to be determined based on the size of the picture to be displayed.   = .RGB_565;//Set picture format  Bitmap bitmap = (inputStream, null, option);

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.