It is very convenient to use frameworks such as xUtils, but today we need to use code to implement the function of bitmapUtils, which is very simple.
AsyncTask requests a picture
####AsyncTask
#####AsyncTask is a thread pool + handler encapsulation. The first generic is: the parameter type type of the parameter (which is consistent with doInBackground). The second generic is:
#####The parameter type of the update progress (consistent with onProgressUpdate) The third generic: The parameter type of the return result (consistent with onPostExecute,
###### and doInBackground return types are the same)
See the AsyncTask source code:
public abstract class AsyncTask<Params, Progress, Result> { private static final String LOG_TAG = "AsyncTask"; private static final int CORE_POOL_SIZE = 5; private static final int MAXIMUM_POOL_SIZE = 128; private static final int KEEP_ALIVE = 1; private static final ThreadFactory sThreadFactory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); public Thread newThread(Runnable r) { return new Thread(r, "AsyncTask #" + ()); } };
Core thread 5 Maximum thread 128 This is the thread pool of AsyncTask. Then send a message through the handler. It internally instantiates a static custom class InternalHandler. This class is inherited from the Handler. An object called AsyncTaskResult is bound to this custom class. Every time the child thread needs to notify the main thread, it calls sendToTarget to send a message to the handler itself. Then in the handleMessage of the handler, AsyncTaskResult performs different operations according to the type of message (for example, MESSAGE_POST_PROGRESS will update the progress bar, and MESSAGE_POST_CANCEL cancels the task). It is worth mentioning that these operations are performed in the UI thread, which means that once the child thread needs to interact with the UI thread, the handler object is automatically called internally and placed in the main thread.
private static final InternalHandler sHandler = new InternalHandler(); mFuture = new FutureTask<Result>(mWorker) { @Override protected void More ...done() { Message message; Result result = null; try { result = get(); } catch (InterruptedException e) { (LOG_TAG, e); } catch (ExecutionException e) { throw new RuntimeException("An error occured while executing doInBackground()", ()); } catch (CancellationException e) { message = (MESSAGE_POST_CANCEL, new AsyncTaskResult<Result>(, (Result[]) null)); (); return; } catch (Throwable t) { throw new RuntimeException("An error occured while executing " + "doInBackground()", t); } message = (MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(, result)); (); } }; private static class InternalHandler extends Handler { @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) @Override public void More ...handleMessage(Message msg) { AsyncTaskResult result = (AsyncTaskResult) ; switch () { case MESSAGE_POST_RESULT: // There is only one result ([0]); break; case MESSAGE_POST_PROGRESS: (); break; case MESSAGE_POST_CANCEL: (); break; } } }
Let’s look at the code below. The first step is to request a picture and parse the comments.
import ; import ; import ; import ; import ; import ; import ; /** * Network cache * * @author Ace * @date 2016-02-18 */ public class NetCacheUtils { private LocalCacheUtils mLocalUtils; private MemoryCacheUtils mMemoryUtils; public NetCacheUtils(LocalCacheUtils localUtils, MemoryCacheUtils memoryUtils) { mLocalUtils = localUtils; mMemoryUtils = memoryUtils; } public void getBitmapFromNet(ImageView imageView, String url) { BitmapTask task = new BitmapTask(); (imageView, url); } /** * AsyncTask is the thread pool + handler encapsulation. The first generic is: the parameter type type of the parameter (which is consistent with doInBackground). The second generic is: * The parameter type of the update progress (consistent with onProgressUpdate) The third generic: the parameter type of the return result (consistent with onPostExecute, * The return type is the same as doInBackground) */ class BitmapTask extends AsyncTask<Object, Integer, Bitmap> { private ImageView mImageView; private String url; // The main thread is running, preloaded @Override protected void onPreExecute() { (); } // The child thread runs, the asynchronous loading logic is processed in this method @Override protected Bitmap doInBackground(Object... params) { mImageView = (ImageView) params[0]; url = (String) params[1]; (url);//Bind imageView and url together // publishProgress(values)// Notify progress // Download the picture return download(url); } // The main thread is running, update progress @Override protected void onProgressUpdate(Integer... values) { (values); } // The main thread is running, update the main interface @Override protected void onPostExecute(Bitmap result) { if (result != null) { // Determine whether the current image is the image you want from the imageView to prevent the image disorder caused by listview reuse String bindUrl = (String) (); if ((url)) { // Set image for imageView (result); // Save the image locally (result, url); // Save the image in memory (url, result); } } } } /** * Download the picture * * @param url */ public Bitmap download(String url) { HttpURLConnection conn = null; try { conn = (HttpURLConnection) (new URL(url).openConnection()); (5000); (5000); ("GET"); (); int responseCode = (); if (responseCode == 200) { InputStream in = (); // Convert streams into bitmap objects Bitmap bitmap = (in); return bitmap; } } catch (Exception e) { (); } finally { if (conn != null) { (); } } return null; } }
It's very easy to use LruCache
I'll simply translate the following document:
* A cache that holds strong references to a limited number of values. Each time * a value is accessed, it is moved to the head of a queue. When a value is * added to a full cache, the value at the end of that queue is evicted and may * become eligible for garbage collection. * CacheSave a strong quote to limit the amount of content,wheneverItemWhen visited,thisItemIt will move to the head of the queue。 * whencacheAdd new ones when they are fullitemhour,At the end of the queueitemWill be recycled。 * <p>If your cached values hold resources that need to be explicitly released, * override {@link #entryRemoved}. * if youcacheA certain value of need to be explicitly released,RewriteentryRemoved() * <p>By default, the cache size is measured in the number of entries. Override * {@link #sizeOf} to size the cache in different units. For example, this cache * is limited to 4MiB of bitmaps: defaultcacheSize is measureditemNumber of,RewritesizeofCalculate differentlyitemof * size。 {@code * int cacheSize = 4 * 1024 * 1024; // 4MiB * LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) { * protected int sizeOf(String key, Bitmap value) { * return (); * } * }} ------------------------------------------------------------------- <p>This class is thread-safe. Perform multiple cache operations atomically by * synchronizing on the cache: <pre> {@code * synchronized (cache) { * if ((key) == null) { * (key, value); * } * }}</pre> * 他是线程安全of,Automatically perform multiple cache operations and lock them ------------------------- <p>This class does not allow null to be used as a key or value. A return * value of null from {@link #get}, {@link #put} or {@link #remove} is * unambiguous: the key was not in the cache. * Not allowedkeyorvaluefornull * whenget(),put(),remove()返回值fornullhour,key相应of项不在cachemiddle
The most important thing is probably the above points: It is very simple to use
Let's see the code:
import ; import .; /** * Memory cache tool class * * @author Ace * @date 2016-02-19 */ public class MemoryCacheUtils { // Android 2.3 (API Level // 9) Starting, the garbage collector will be more inclined to recycle objects holding soft or weak references, which makes soft and weak references no longer reliable. It is recommended to use LruCache, which is a strong reference private LruCache<String, Bitmap> mCache; public MemoryCacheUtils() { int maxMemory = (int) ().maxMemory();// Get the maximum memory allocated by the virtual machine // 16M // LRU is used at least recently, and the memory overflow is solved by controlling the memory to not exceed the maximum value (specified by the developer). As translated above, if the cache is full, it will clean up the cache object that is least recently used. mCache = new LruCache<String, Bitmap>(maxMemory / 8) { @Override protected int sizeOf(String key, Bitmap value) { // Calculate the size of a bitmap int size = () * ();// The number of bytes in each line is multiplied by height return size; } }; } public Bitmap getBitmapFromMemory(String url) { return (url); } public void setBitmapToMemory(String url, Bitmap bitmap) { (url, bitmap); } }
Last level cache Local cache Save the image downloaded from the network in the form of MD5 to the memory card's formulation directory
/** * Local cache tool class * * @author Ace * @date 2016-02-19 */ public class LocalCacheUtils { // Image cache folder public static final String DIR_PATH = Environment .getExternalStorageDirectory().getAbsolutePath() + "/ace_bitmap_cache"; public Bitmap getBitmapFromLocal(String url) { try { File file = new File(DIR_PATH, (url)); if (()) { Bitmap bitmap = (new FileInputStream( file)); return bitmap; } } catch (Exception e) { (); } return null; } public void setBitmapToLocal(Bitmap bitmap, String url) { File dirFile = new File(DIR_PATH); // Create folder. The folder does not exist or it is not a folder. Create a folder. The difference between mkdirs and mkdir is that if the folder has several layers of paths, the former will create the missing parent directory. The latter will not create these parent directories. if (!() || !()) { (); } try { File file = new File(DIR_PATH, (url)); // Save the image compression locally, see 1: Compression format; see 2: Compression quality (0-100); see 3: Output stream (, 100, new FileOutputStream(file)); } catch (Exception e) { (); } } }
MD5Encoder
import ; public class MD5Encoder { public static String encode(String string) throws Exception { byte[] hash = ("MD5").digest(("UTF-8")); StringBuilder hex = new StringBuilder( * 2); for (byte b : hash) { if ((b & 0xFF) < 0x10) { ("0"); } ((b & 0xFF)); } return (); } }
Finally, create a new tool class to use our three cache methods above
/** * Level 3 cache tool class * * @author Ace * @date 2016-02-19 */ public class MyBitmapUtils { // Network caching tool class private NetCacheUtils mNetUtils; // Local cache tool class private LocalCacheUtils mLocalUtils; // Memory cache tool class private MemoryCacheUtils mMemoryUtils; public MyBitmapUtils() { mMemoryUtils = new MemoryCacheUtils(); mLocalUtils = new LocalCacheUtils(); mNetUtils = new NetCacheUtils(mLocalUtils, mMemoryUtils); } public void display(ImageView imageView, String url) { // Set default loading of pictures (.news_pic_default); // Load from memory cache first Bitmap bitmap = (url); if (bitmap != null) { (bitmap); ("Reading pictures from memory..."); return; } // Load from local cache bitmap = (url); if (bitmap != null) { (bitmap); ("Read pictures from local..."); // Set pictures for memory (url, bitmap); return; } // Load from network cache (imageView, url); } }
The above is all about this article, I hope it will be helpful for everyone to learn Android software programming.