Original: http://www.cnblogs.com/ghj1976/archive/2011/05/06/2038738.html#3018499
In learning "Android Asynchronous Loading image Summary" This article, found that some areas did not write clearly, I based on my understanding, the code of this article rewrite, and the following is my collation.
The following test uses the layout file:
Simply put, the linearlayout layout, which has been decentralized by 5 ImageView.
<?xml version= "1.0" encoding= "Utf-8"? ><linearlayout xmlns:android= "http://schemas.android.com/apk/res/ Android "android:orientation=" vertical "android:layout_width=" fill_parent "android:layout_height=" Fill_parent " ><textview android:text= "Picture area Start" android:id= "@+id/textview2" android:layout_width= "Wrap_content" Android: layout_height= "Wrap_content" ></textview><imageview android:id= "@+id/imageview1" Android:layout_ height= "Wrap_content" android:src= "@drawable/icon" android:layout_width= "Wrap_content" ></ImageView>< ImageView android:id= "@+id/imageview2" android:layout_height= "wrap_content" android:src= "@drawable/icon" Android: Layout_width= "Wrap_content" ></imageview><imageview android:id= "@+id/imageview3" Android:layout_ height= "Wrap_content" android:src= "@drawable/icon" android:layout_width= "Wrap_content" ></ImageView>< ImageView android:id= "@+id/imageview4" android:layout_height= "wrap_content" android:src= "@drawable/icon" Android: Layout_width= "WRap_content "></imageview><imageview android:id=" @+id/imageview5 "android:layout_height=" wrap_content "Android:src=" @drawable/icon "android:layout_width=" wrap_content "></imageview><textview android:text = "Picture area End" android:id= "@+id/textview1" android:layout_width= "wrap_content" android:layout_height= "Wrap_content" ></TextView></LinearLayout>
The logic we will demonstrate is to asynchronously download 5 different images from the server and put them into these 5 imageview in turn. The top and bottom 2 TextView are designed to make it easier for us to see if we are blocking the UI display.
Of course the network access permissions are configured in the Androidmanifest.xml file.
<uses-permission android:name= "Android.permission.INTERNET" ></uses-permission>
handler+runnable mode
Let's take a look at an example that is not an async line preempted, using handler+runnable mode.
Why is this not a new thread? See this article: Android Runnable running on that thread here the code actually downloads the picture in the main UI, not the new one.
When we run the code below, we find that he is actually blocking the display of the entire interface, which requires all images to be loaded before the interface can be displayed.
Package ghj1976. Androidtest;import Java.io.ioexception;import Java.net.url;import Android.app.activity;import Android.graphics.drawable.drawable;import Android.os.bundle;import Android.os.handler;import Android.os.systemclock;import Android.util.log;import Android.widget.imageview;public class MainActivity extends Activity {@Overridepublic void onCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.main); LoadImage ("Http://www.baidu.com/img/baidu_logo.gif", R.id.imageview1); LoadImage ( Http://www.chinatelecom.com.cn/images/logo_new.gif ", r.id.imageview2); LoadImage (" http://cache.soso.com/30d/img/ Web/logo.gif, R.ID.IMAGEVIEW3); LoadImage ("Http://csdnimg.cn/www/images/csdnindex_logo.gif", R.ID.IMAGEVIEW4); LoadImage ("Http://images.cnblogs.com/logo_small.gif", R.ID.IMAGEVIEW5);} Private Handler Handler = new Handler ();p rivate void LoadImage (final String URL, final int id) {handler.post (New Runnable ( {public void Run () {drawable drawable = null;try {drawable = drawable.createfromstream (new URL). OpenStream (), "Image.gif");} catch (IOException e) {log.d ("test", E.getmessage ());} if (drawable = = null) {LOG.D ("test", "null Drawable"),} else {log.d ("test", "NOT null drawable");} Network latency simulated in order to test the cache
((ImageView) MainActivity.this.findViewById (ID)). setimagedrawable (drawable);}});}
Handler+thread+message mode
This mode uses threads, so you can see the effect of asynchronous loading.
Core code:
Package ghj1976. Androidtest;import Java.io.ioexception;import Java.net.url;import Android.app.activity;import Android.graphics.drawable.drawable;import Android.os.bundle;import Android.os.handler;import android.os.Message; Import Android.os.systemclock;import Android.util.log;import Android.widget.imageview;public class MainActivity Extends Activity {@Overridepublic void onCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.main); LoadImage2 ("Http://www.baidu.com/img/baidu_logo.gif", r.id.imageview1); loadImage2 ("Http://www.chinatelecom.com.cn/images/logo_new.gif", r.id.imageview2); LoadImage2 ("http://cache.soso.com/30d/ Img/web/logo.gif ", R.ID.IMAGEVIEW3); LoadImage2 (" Http://csdnimg.cn/www/images/csdnindex_logo.gif ", R.ID.IMAGEVIEW4); LoadImage2 ("Http://images.cnblogs.com/logo_small.gif", R.ID.IMAGEVIEW5);} Final Handler handler2 = new Handler () {@Overridepublic void Handlemessage (Message msg) {(ImageView) mainactivity.this.f Indviewbyid (MSG.ARG1)). SetimAgedrawable ((drawable) msg.obj);}};/ /use Handler+thread mode for multithreaded asynchronous loading private void LoadImage2 (final String URL, final int id) {Thread thread = new Thread () {@Overr idepublic void Run () {drawable drawable = null;try {drawable = drawable.createfromstream (new URL (URL). OpenStream (), "imag E.png ");} catch (IOException e) {log.d ("test", E.getmessage ());} Analog Network Delay Systemclock.sleep (2000); Message message = Handler2.obtainmessage (); message.arg1 = Id;message.obj = drawable;handler2.sendmessage (message);}}; Thread.Start (); thread = null;}}
At this time we can see the implementation of asynchronous loading, when the interface is open, five imageview are not graphs, and then after the respective thread download, the diagram automatically updated up.
Handler+executorservice (thread pool) +messagequeue mode
After all, the number of threads can be limited, we can not open a lot of thread, especially for mobile phones.
This example is using the thread pool. Android has the same Executorservice implementation as Java, and we're going to use it.
The basic idea of the thread pool is also the idea of an object pool, which opens up a memory space in which many (not dead) threads are stored, and the thread execution schedule is handled by the pool manager. When a thread task is taken from a pool, the threads object is pooled after execution, which avoids the performance overhead of repeatedly creating thread objects and saves system resources.
The thread pool information can be see this article: java&android thread pool-executorservice The following example is a thread pooling that creates a reusable fixed number of threads.
Core code
Package ghj1976. Androidtest;import Java.io.ioexception;import Java.net.url;import Java.util.concurrent.executorservice;import Java.util.concurrent.executors;import Android.app.activity;import Android.graphics.drawable.drawable;import Android.os.bundle;import Android.os.handler;import Android.os.message;import Android.os.systemclock;import Android.util.log;import Android.widget.imageview;public class Mainactivity extends Activity {@Overridepublic void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (r.layout.main); loadImage3 ("Http://www.baidu.com/img/baidu_logo.gif", R.id.imageview1); LoadImage3 ("http://www.chinatelecom.com.cn/images/ Logo_new.gif ", r.id.imageview2); LoadImage3 (" Http://cache.soso.com/30d/img/web/logo.gif ", R.ID.IMAGEVIEW3); LoadImage3 ("Http://csdnimg.cn/www/images/csdnindex_logo.gif", r.id.imageview4); LoadImage3 ("http:// Images.cnblogs.com/logo_small.gif ", r.id.imageview5);} Private Handler Handler = new Handler ();p rivate executorservice execUtorservice = Executors.newfixedthreadpool (5);//introduction of thread pool to manage multi-threaded private void LoadImage3 (final String URL, final int id) {EXEC Utorservice.submit (New Runnable () {public void run () {try {final drawable drawable = Drawable.createfromstream (New URL (Ur L). OpenStream (), "image.png");//Analog Network delay systemclock.sleep (+); Handler.post (new Runnable () {public void Run () {( ImageView) MainActivity.this.findViewById (ID)). setimagedrawable (drawable);});} catch (Exception e) {throw new RuntimeException (e);}});}}
Here we are using the Handler.post (new Runnable () {Update before the first step, of course, in the UI main thread, we also have Executorservice.submit (new Runnable () { To make sure that the download is in the thread of the online pool.
Handler+executorservice (thread pool) +messagequeue+ cache mode
Here are a few modifications compared to the previous one:
- Encapsulate the entire code in a class
- To avoid problems with downloading the same picture multiple times, a local cache is used
Encapsulated class:
Package ghj1976. Androidtest;import java.lang.ref.softreference;import java.net.url;import Java.util.hashmap;import java.util.Map; Import Java.util.concurrent.executorservice;import Java.util.concurrent.executors;import Android.graphics.drawable.drawable;import Android.os.handler;import Android.os.systemclock;public Class AsyncImageLoader3 {//In order to speed up the cache in memory (mainly applied to duplicate pictures, or the same picture to be accessed multiple times, such as in the ListView) public map<string, softreference<drawable>> Imagecache = new hashmap<string, softreference<drawable>> ();p rivate Executorservice Executorservice = Executors.newfixedthreadpool (5); Fixed five threads to perform the task private final Handler Handler = new Handler ();/** * * @param imageUrl * Image URL address * @param callbac K * Callback Interface * @return returns an in-memory cached image, the first load returns null */public drawable loaddrawable (final String imageurl,final imagecallb ACK callback) {//if (Imagecache.containskey (IMAGEURL)) {softreference<drawable> SoftReference = If cached, the data is fetched from the cache Imagecache.get (IMAGEURL); if (SOFTreference.get ()! = null) {return softreference.get ();}} There is no image in the cache, the data is fetched from the network and the fetched data is cached in memory Executorservice.submit (new Runnable () {public void run () {try {final drawable drawable = Loadimagefromurl (IMAGEURL); Imagecache.put (IMAGEURL, New softreference<drawable> (drawable)); Handler.post (new Runnable () {public void run () {callback.imageloaded (drawable);}});} catch (Exception e) {throw new RuntimeException (e);}}); return null;} To fetch data from a network method protected drawable Loadimagefromurl (String imageUrl) {try {//test, simulate network delay, the actual line of code cannot have Systemclock.sleep (2000 ); return Drawable.createfromstream (New URL (IMAGEURL). OpenStream (), "image.png");} catch (Exception e) {throw new RuntimeException (e);}} Callback interface open to the outside public interface Imagecallback {//Note this method is used to set the target object's image resource public void imageloaded (drawable imagedrawable);}}
Description
The final parameter is when the function argument is the final type, you can read the parameter, but the value of the parameter cannot be changed. See: Java keyword final, static usage summary
Here softreference is used to solve the memory shortage error (OUTOFMEMORYERROR), in more detail see: Memory-Optimized two classes: SoftReference and WeakReference
Previous segment Call:
Package ghj1976. Androidtest;import Android.app.activity;import Android.graphics.drawable.drawable;import Android.os.Bundle;import Android.widget.imageview;public class Mainactivity extends Activity {@Overridepublic void OnCreate (Bundle Savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.main); LoadImage4 ("http:// Www.baidu.com/img/baidu_logo.gif ", r.id.imageview1); LoadImage4 (" Http://www.chinatelecom.com.cn/images/logo_ New.gif ", r.id.imageview2); LoadImage4 (" Http://cache.soso.com/30d/img/web/logo.gif ", R.ID.IMAGEVIEW3); LoadImage4 ( "Http://csdnimg.cn/www/images/csdnindex_logo.gif", r.id.imageview4); LoadImage4 ("Http://images.cnblogs.com/logo_ Small.gif ", r.id.imageview5);} Private AsyncImageLoader3 AsyncImageLoader3 = new AsyncImageLoader3 ();//introduces the thread pool and introduces the memory caching function, and encapsulates the interface for external calls, simplifying the calling process private void LoadImage4 (Final String URL, final int id) {//If cached, the image is removed from the cache, and the method in the Imagecallback interface is not executed drawable cacheimage = Asyncim Ageloader3.loaddrawable (url,new asyncimageloader3.imagecallback () {See implementation: If the URL is first loaded, the following method executes public void imageloaded (drawable imagedrawable) {(ImageView) Findviewbyid (ID)). Setimagedrawable (imagedrawable);}}); if (cacheimage! = null) {((ImageView) Findviewbyid (ID)). setimagedrawable (Cacheimage);}}
Resources:
Android Asynchronous Load Image summary
Http://blog.csdn.net/sgl870927/archive/2011/03/29/6285535.aspx
Evolutionary understanding Android Asynchronous load Picture