The current Android development has so far excellent picture loading framework too many, such as: Volley, picasso,imageloader,glide and so on. But as a program ape, understand the principle of implementation is still very important, only understand to better use. So, today I simply design a network load picture frame. The main is familiar with the image of the network loading mechanism.
In general, an excellent picture loading framework (Imageloader) should have the following features:
Picture compression
Memory Cache
Disk caching
Synchronized loading of pictures
Asynchronous loading of pictures
Network Pull
Then we will introduce from the above several aspects:
1. Image compression (effective reduction of the probability of occurrence of oom)
Image compression features I have done in the efficient loading of bitmap has been introduced here is not much to say directly on the code. Here is a direct abstraction of a class to complete the image compression function.
public class Imageresizer {private static final String TAG = "Imageresizer";
Public Imageresizer () {super (); TODO auto-generated Constructor stub} public Bitmap Decodesampledbitmapfromresource (resources res, int resid,
T reqwidth, int reqheight) {final bitmapfactory.options Options = new Bitmapfactory.options ();
Options.injustdecodebounds = true;
Bitmapfactory.decoderesource (res, resid, options);
Options.insamplesize = calculateinsamplesize (options, Reqwidth, reqheight);
Options.injustdecodebounds = false;
Return Bitmapfactory.decoderesource (res, resid, options); Public Bitmap Decodesampledbitmapfrombitmapfiledescriptor (filedescriptor fd, int reqwidth,int reqheight) {final B
Itmapfactory.options Options = new Bitmapfactory.options ();
Options.injustdecodebounds = true;
Bitmapfactory.decodefiledescriptor (FD, NULL, options);
Options.insamplesize = calculateinsamplesize (options, Reqwidth, reqheight); Options.injustdecodebounds = false;
Return Bitmapfactory.decodefiledescriptor (FD, NULL, options);
}
public int calculateinsamplesize (bitmapfactory.options Options,
int reqwidth, int reqheight) {
final int width = Options.outwidth;
Final int height = options.outheight;
int insamplesize = 1;
if (Height > reqheight | | | width > reqwidth) {
final int halfheight = HEIGHT/2;
Final int halfwidth = WIDTH/2;
while ((halfheight/insamplesize) > Reqheight
&& (halfwidth/insamplesize) > Halfwidth) {
Insamp Lesize *= 2;
}
Return insamplesize
}
}
2. Memory Cache and Disk cache
The cache directly selects LruCache and Disklrucache to complete the memory cache and disk cache work.
Initialize it first:
Private lrucache<string, bitmap> Mmemorycache;
Private Disklrucache Mdisklrucache;
Public Imageloader {
mcontext = Context.getapplicationcontext ();
The allocated memory cache is 1/8 of the current process, and the disk cache capacity is 50M
int maxmemory = (int) (Runtime.getruntime (). MaxMemory () * 1024);
int cacheSize = MAXMEMORY/8;
Mmemorycache = new lrucache<string, bitmap> (cacheSize) {
@Override
protected int sizeOf (String key, Bitmap value) {return
value.getrowbytes () * value.getheight ()/1024;
}
};
File Diskcachedir = Getdiskchahedir (Mcontext, "Bitmap");
if (!diskcachedir.exists ()) {
diskcachedir.mkdirs ();
}
if (Getusablespace (Diskcachedir) > Disk_cache_size) {
try {
Mdisklrucache = Disklrucache.open ( Diskcachedir, 1, 1,
disk_cache_size);
Misdisklrucachecreated = true;
} catch (IOException e) {
e.printstacktrace ();}}}
Once created, the next step is to provide a way to view additions and features. First look at the memory cache.
private void Addbitmaptomemorycache (String key, Bitmap Bitmap) {
if (getbitmapfrommemcache (key) = null) {
Mmemorycache.put (key, bitmap);
}
Private Bitmap Getbitmapfrommemcache (String key) {return
mmemorycache.get (key);
}
Memory caching is relatively simple, and disk caching is much more complex. Disk caching (Lrudiskcache) does not provide a way to implement the method directly, but to add and read the file system through editor and snapshot.
First look at Editor, which provides a commit and abort method to commit and undo write operations to the file system.
Writes the downloaded picture to the file system, implementing the disk cache
private Bitmap loadbitmapfromhttp (String url, int reqwidth, int reqheight)
throws IOException {
if (looper.mylooper () = = Looper.getmainlooper ()) {
throw new RuntimeException ("Can not visit Network from UI Thread. ");
if (Mdisklrucache = null) return
null;
String key = Hashkeyformurl (URL);
Disklrucache.editor Editor = Mdisklrucache.edit (key);
if (editor!= null) {
OutputStream outputstream = Editor
. Newoutputstream (disk_cache_index);
if (Downloadurltostream (URL, outputstream)) {
editor.commit ();
} else {
editor.abort ();
}
}
Mdisklrucache.flush ();
Return Loadbitmapfordiskcache (URL, reqwidth, reqheight);
}
Snapshot, it can get the disk cache object corresponding to the FileInputStream, but fileinputstream not easy to compress, so through the filedescriptor to load the compressed image, Finally, the loaded bitmap is added to the memory cache.
Public Bitmap loadbitmapfordiskcache (String url, int reqwidth, int reqheight)
throws IOException {
if ( Looper.mylooper () = = Looper.getmainlooper ()) {
LOG.W (TAG, "load bitmap from UI Thread, it's not recommended");
if (Mdisklrucache = null) return
null;
Bitmap Bitmap = null;
String key = Hashkeyformurl (URL);
Disklrucache.snapshot Snapshot = Mdisklrucache.get (key);
if (snapshot!= null) {
FileInputStream FileInputStream = (fileinputstream) snapshot
. getInputStream (disk_ Cache_index);
FileDescriptor filedescriptor = Fileinputstream.getfd ();
Bitmap = Mimageresizer.decodesampledbitmapfrombitmapfiledescriptor (
filedescriptor, Reqwidth, reqHeight);
if (bitmap!= null) {
Addbitmaptomemorycache (key, bitmap);
}
}
return bitmap;
}
3. Synchronous loading
Methods that are loaded synchronously need to be called externally in child threads.
Synchronous load Public
Bitmap LoadBitmap (String uri, int reqwidth, int reqheight) {Bitmap Bitmap
= Loadbitmpafrommemcache (URI);
if (bitmap!= null) {return
bitmap;
}
try {
bitmap = Loadbitmapfordiskcache (URI, Reqwidth, reqheight);
if (bitmap!= null) {return
bitmap;
}
Bitmap = Loadbitmapfromhttp (URI, Reqwidth, reqheight);
} catch (IOException e) {
e.printstacktrace ();
}
if (bitmap = = null &&!misdisklrucachecreated) {
bitmap = Downloadbitmapfromurl (URI);
}
return bitmap;
}
You can see from the method that the work process follows the following steps:
First try to read the picture from the memory cache, and then try to read the picture from the disk cache before pulling it from the network. This method can no longer be executed in the main thread, and the detection of the execution environment is implemented in Loadbitmapfromhttp.
if (looper.mylooper () = = Looper.getmainlooper ()) {
throw new RuntimeException ("Can not visit network the from UI Thread." );
}
4. Asynchronous loading
Asynchronously loads the public
void Bindbitmap (Final String URI, final ImageView imageview, final
int reqwidth, final int reqheight ) {
Imageview.settag (Tag_key_uri, URI);
Bitmap Bitmap = Loadbitmpafrommemcache (URI);
if (bitmap!= null) {
imageview.setimagebitmap (bitmap);
return;
}
Runnable loadbitmaptask = new Runnable () {
@Override public
void Run () {
Bitmap Bitmap = LoadBitmap (URI, re Qwidth, reqheight);
if (bitmap!= null) {
Loaderresult result = new Loaderresult (ImageView, Uri,
bitmap);
Mmainhandler.obtainmessage (Message_post_result, result)
sendtotarget ();
}}
}
;
Thread_pool_executor.execute (Loadbitmaptask);
}
From the Bindbitmap implementation, the Bindbitmap method will try to read the picture from the memory cache, if the reading succeeds directly return the result, otherwise it will call the LoadBitmap method in the thread pool, when the picture is successfully loaded and then the picture, The address of the picture and the imageview that need to be bound are encapsulated into a Loaderresult object, and then sent a message to the main thread via Mmainhandler, so that you can set the picture for ImageView in the main thread.
Let's take a look at the thread pool and handler used in this method, first bindbitmap the thread pool Thread_pool_executor implementation.
private static final int cpu_count = Runtime.getruntime ()
. Availableprocessors ();
private static final int core_pool_size = Cpu_count + 1;
private static final int maximum_pool_size = Cpu_count * 2 + 1;
Private static final long keep_alive = 10L;
private static final Threadfactory sthreadfactory = new Threadfactory () {
private final atomicinteger mcount = new Ato Micinteger ();
@Override public
Thread Newthread (Runnable r) {
//TODO auto-generated method stub return
new Thread (R, "Ima geloader# "+ mcount.getandincrement ());
}
};
public static final Executor thread_pool_executor = new Threadpoolexecutor (
core_pool_size, Maximum_pool_size, Keep_alive, Timeunit.seconds,
new linkedblockingdeque<runnable> (), sthreadfactory);
1. Reasons for using thread pooling and handler.
First, you can not use the ordinary thread to achieve, if the use of ordinary threads to load pictures, as the list of sliding may produce a large number of threads, this is not conducive to the promotion of efficiency. Handler, the main thread looper is used to construct the Handler object, which makes the imageloader can be constructed in a non main thread. In addition, in order to solve the problem of list dislocation caused by view reuse, the ImageView will check his URL before setting the picture, and if the change is not set to the picture, it will solve the problem of list dislocation.
Private Handler Mmainhandler = new Handler (Looper.getmainlooper ()) {
@Override public
void Handlemessage ( Message msg) {
Loaderresult result = (Loaderresult) msg.obj;
ImageView ImageView = Result.imageview;
Imageview.setimagebitmap (RESULT.BITMAP);
String uri = (string) imageview.gettag (Tag_key_uri);
if (Uri.equals (Result.uri)) {
imageview.setimagebitmap (result.bitmap);
} else {
LOG.W (TAG, "set image Bitmap,but URL has changed, ignored! ");}}
;
Summarize:
The problem of picture loading, especially the loading of a large number of images, has been a troubling problem for Android developers. This article only mentions the most basic one kind of solution, for the study is still good.
The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.