SoFunction
Updated on 2025-04-07

Level 3 caching mechanism for pictures in Android

We cannot let users download it from the Internet every time we load the picture, which not only wastes traffic but also affects the user experience. Therefore, the image caching operation mechanism is introduced in Android.

principle:

First, download the picture on the network based on the network address of the picture, cache the picture first into the memory cache, and cache it into a strong reference, that is, LruCache. If there is insufficient space in a strong reference, the earlier stored image objects will be expelled to softReference for storage, and then the picture will be cached to a file (internal storage external storage); when reading the picture, first read the memory cache to determine whether there is an image in the strong reference. If there is a strong reference, it will be read directly. If there is no such thing as a strong reference, it will be judged whether there is a soft reference. If there is no such thing as a soft reference, add the picture in the soft reference to the strong reference and delete the data in the soft reference. If there is no such thing as a soft reference, read the file storage, and if the file storage does not exist, the network loads.

Download: Network-Memory-File

Read: Memory-Strong Reference-Soft Reference-File-Network

This is the process. Let’s use a simple demo to demonstrate your level 3 cache of images. There is only one interface in this demo. An ImageView on the interface is used to display images, and a button is used to load images when clicked. The layout is as follows:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:andro
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"
android:layout_centerInParent="true"/>
<Button
android:
android:layout_below="@+id/iv_img"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Loading pictures"/>
</RelativeLayout>

Because you need to download data from the network and store it in the local SD card, don't forget to add network access permissions, network status access permissions and write content to external storage devices for the program:

<uses-permission android:name="" />
<uses-permission android:name=".ACCESS_NETWORK_STATE" />
<uses-permission android:name=".WRITE_EXTERNAL_STORAGE" />

Next, create an HttpUtils tool class for accessing the network, the code is as follows:

package ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
/**Network Access Tools
 * Created by Lx on 2016/8/19.
 */
public class HttpUtils {
/**
 * Determine whether the network connection is smooth
 * @param mContext
 * @return
 */
public static boolean isNetConn(Context mContext) {
ConnectivityManager manager = (ConnectivityManager) (Context.CONNECTIVITY_SERVICE);
NetworkInfo info = ();
if (info != null) {
return ();
} else {
return false;
}
}
/**
 * Download data on the network based on path
 * @param path
 * @return Return the downloaded content byte data form
 */
public static byte[] getDateFromNet(String path) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) ();
("GET");
(5000);
(true);
();
if (()==200) {
InputStream is = ();
byte b[] = new byte[1024];
int len;
while ((len=(b))!=-1) {
(b, 0, len);
}
return ();
}
} catch (IOException e) {
();
}
return ();
}
}

There are also tools for operating external storage:

package ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
/**
* Created by Lx on 2016/8/20.
*/
public class ExternalStorageUtils {
/**
 * Store the passed image byte array into the SD card
 * @param imgName The name of the picture
 * @param buff byte array
 * @return Return whether the storage is successful
 */
public static boolean storeToSDRoot(String imgName, byte buff[]) {
boolean b = false;
String basePath = ().getAbsolutePath();
File file = new File(basePath, imgName);
try {
FileOutputStream fos = new FileOutputStream(file);
(buff);
();
b = true;
} catch (IOException e) {
();
}
return b;
}
/**
 * Get pictures from local memory based on the picture name
 * @param imgName Image name
 * @return Return to the Bitmap format of the image
 */
public static Bitmap getImgFromSDRoot(String imgName) {
Bitmap bitmap = null;
String basePath = ().getAbsolutePath();
File file = new File(basePath, imgName);
try {
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte b[] = new byte[1024];
int len;
while ((len = (b)) != -1) {
(b, 0, len);
}
byte buff[] = ();
if (buff != null &amp;&amp;  != 0) {
bitmap = (buff, 0, );
}
} catch (IOException e) {
();
}
return bitmap;
}
}

In this example, the image is stored in the root directory of the SD card by default.

Then there is the main main function:

package ;
import ;
import ;
import ;
import ;
import ;
import .;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
public class MainActivity extends AppCompatActivity implements  {
private Button btn_download;
private ImageView iv_img;
private MyLruCache myLruCache;
private LinkedHashMap&lt;String, SoftReference&lt;Bitmap&gt;&gt; cashMap = new LinkedHashMap&lt;&gt;();
private static final String TAG = "MainActivity";
private String imgPath = "http:///UploadFiles/201212/Medium_20121217143424221.jpg";
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
Bitmap bitmap = (Bitmap) ;
iv_img.setImageBitmap(bitmap);
(, "Download pictures from the Internet", Toast.LENGTH_SHORT).show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
(savedInstanceState);
setContentView(.activity_main);
initView();
int totalMemory = (int) ().maxMemory();
int size = totalMemory / 8;
myLruCache = new MyLruCache(size);
btn_download.setOnClickListener(this);
}
private void initView() {
btn_download = (Button) findViewById(.btn_download);
iv_img = (ImageView) findViewById(.iv_img);
}
@Override
public void onClick(View v) {
Bitmap b = getImgCache();
if (b != null) {
iv_img.setImageBitmap(b);
} else {
new Thread(new Runnable() {
@Override
public void run() {
if (()) {
byte b[] = (imgPath);
if (b != null &amp;&amp;  != 0) {
Bitmap bitmap = (b, 0, );
Message msg = ();
 = bitmap;
(msg);
(imgPath, bitmap);
(TAG, "run: " + "Cache into strong reference successfully");
boolean bl = ("", b);
if (bl) {
(TAG, "run: " + "Cache to local memory successfully");
} else {
(TAG, "run: " + "Cache to local memory failed");
}
} else {
(, "Download failed!", Toast.LENGTH_SHORT).show();
}
} else {
(, "Please check your network!", Toast.LENGTH_SHORT).show();
}
}
}).start();
}
}
/**
 * Get the image from the cache
 *
 * @return Return the obtained Bitmap
 */
public Bitmap getImgCache() {
Bitmap bitmap = (imgPath);
if (bitmap != null) {
(TAG, "getImgCache: " + "Get pictures from LruCache");
} else {
SoftReference&lt;Bitmap&gt; sr = (imgPath);
if (sr != null) {
bitmap = ();
(imgPath, bitmap);
(imgPath);
(TAG, "getImgCache: " + "Get pictures from soft references");
} else {
bitmap = ("");
(TAG, "getImgCache: " + "Get pictures from external storage");
}
}
return bitmap;
}
/**
 * Customize a method inheritance system's LruCache method
 */
public class MyLruCache extends LruCache&lt;String, Bitmap&gt; {
/**
 * The constructor that must be rewritten to define the size of the strong reference cache area
 * @param maxSize for caches that do not override {@link #sizeOf}, this is
 * the maximum number of entries in the cache. For all other caches,
 * this is the maximum sum of the sizes of the entries in this cache.
 */
public MyLruCache(int maxSize) {
super(maxSize);
}
//Return the size of each picture@Override
protected int sizeOf(String key, Bitmap value) {
//Get the number of bytes and line height of each line of the current variable (basically a fixed writing method, I can't remember it and memorize it for me!)return () * ();
}
/**
 * Functions that callback when data in LruCache is evicted or removed
 *
 * @param evicted Changes when data in LruCache is evicted to pour space for new value
 * @param key is used to indicate the key of the object. Generally, when put, the URL address of the image is passed in.
 * @param oldValue Old object stored before
 * @param newValue New object stored
 */
@Override
protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
if (evicted) {
/**
 * Save the old value into a soft reference, because multiple values ​​may be expelled in a strong reference.
 * So create a LinkedHashMap<String, SoftReference<Bitmap>> to store soft references
 * Basically, it is also a fixed writing method
 */
SoftReference&lt;Bitmap&gt; softReference = new SoftReference&lt;Bitmap&gt;(oldValue);
(key, softReference);
}
}
}
}

The basic ideas are written in the code comments in detail. The main thing is to customize a class to inherit the system's LruCache, implement two main methods, sizeOf() and entryRemoved(), and also the constructor that must be rewrited.

The above is the complete description of the third-level caching mechanism of pictures in Android introduced to you by the editor. I hope it will be helpful to you. If you have any questions, please leave me a message. The editor will reply you in time. Thank you very much for your support for my website!