zoukankan      html  css  js  c++  java
  • listview中getview异步加载网络图片

    前言:本以为异步加载挺简单,因为网上代码多,但真想要做好,还真不那么简单,从看代码到弄懂再到自己写,实在是有太多的东西需要学了,用了两天的时间,终于弄出来了,因为用到回调函数,所以理解起来可能难度有点大,讲起来也不太好讲,我尽力讲的明白些,其实还是要多看代码,自己摸索摸索,动手写写就什么都理解了。这篇我们只讲怎样实现异步加载,对于滑动时停止加载的事下篇再讲。

    实现效果:

    1、异步加载图片,在加载图片时,先加载一个默认的图片,然后在后台加载图片,加载完成后显示出来;

    2、当用户在滑动时,停止加载图片的线程,当停止滑动时,看哪几个ITEM在显示屏内,只加载这几个,其它线程保持阻止;(下篇再讲)

    效果图:

              刚开始加载时                          向下划动(新划出来的是空白块)           停划,加载完成

       

    一、XML

    1、main.xml

    1. <?xml version="1.0" encoding="utf-8"?> 
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    3.     android:orientation="vertical" 
    4.     android:layout_width="fill_parent" 
    5.     android:layout_height="fill_parent" 
    6.    
    7.     <ListView android:id="@+id/list"  
    8.         android:layout_width="fill_parent"  
    9.         android:layout_height="fill_parent" /> 
    10. </LinearLayout
    <?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"
        >
        <ListView android:id="@+id/list" 
            android:layout_width="fill_parent" 
            android:layout_height="fill_parent" />
    </LinearLayout>
    

    2、列表子项XML(book_item_adapter.xml)

    1. <?xml version="1.0" encoding="UTF-8"?> 
    2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    3.     android:layout_width="fill_parent" 
    4.     android:layout_height="70.0dip" 
    5.     android:background="@drawable/item" 
    6.     android:drawingCacheQuality="high" 
    7.     android:minHeight="70.0dip" 
    8.     android:orientation="horizontal"
    9.  
    10.     <ImageView 
    11.         android:id="@+id/sItemIcon" 
    12.         android:layout_width="42.0dip" 
    13.         android:layout_height="54.0dip" 
    14.         android:layout_margin="10.0dip" 
    15.         android:background="@drawable/rc_item_bg" 
    16.         android:padding="2.0dip" 
    17.         android:scaleType="fitXY" /> 
    18.  
    19.     <TextView 
    20.         android:text="斗破苍穹" 
    21.         android:id="@+id/sItemTitle" 
    22.         android:layout_width="fill_parent" 
    23.         android:layout_height="30.0dip" 
    24.         android:layout_alignTop="@+id/sItemIcon" 
    25.         android:layout_toRightOf="@+id/sItemIcon" 
    26.         android:gravity="center_vertical" 
    27.         android:singleLine="true" 
    28.         android:textColor="#ffffff" 
    29.         android:textSize="18.0sp" /> 
    30. </RelativeLayout
    <?xml version="1.0" encoding="UTF-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="70.0dip"
        android:background="@drawable/item"
        android:drawingCacheQuality="high"
        android:minHeight="70.0dip"
        android:orientation="horizontal" >
    
        <ImageView
            android:id="@+id/sItemIcon"
            android:layout_width="42.0dip"
            android:layout_height="54.0dip"
            android:layout_margin="10.0dip"
            android:background="@drawable/rc_item_bg"
            android:padding="2.0dip"
            android:scaleType="fitXY" />
    
        <TextView
            android:text="斗破苍穹"
            android:id="@+id/sItemTitle"
            android:layout_width="fill_parent"
            android:layout_height="30.0dip"
            android:layout_alignTop="@+id/sItemIcon"
            android:layout_toRightOf="@+id/sItemIcon"
            android:gravity="center_vertical"
            android:singleLine="true"
            android:textColor="#ffffff"
            android:textSize="18.0sp" />
    </RelativeLayout>

    二、JAVA代码

    1、主页面代码(AsyncListImage.java)

    1. package cn.wangmeng.test; 
    2.  
    3. import java.util.ArrayList; 
    4. import java.util.List; 
    5.  
    6. import android.app.Activity; 
    7. import android.os.Bundle; 
    8. import android.widget.ListView; 
    9.  
    10. public class AsyncListImage extends Activity { 
    11.     private ListView list; 
    12.     @Override 
    13.     public void onCreate(Bundle savedInstanceState) { 
    14.         super.onCreate(savedInstanceState); 
    15.         setContentView(R.layout.main); 
    16.         list=(ListView)findViewById(R.id.list); 
    17.         List<ImageAndText> dataArray=new ArrayList<ImageAndText>(); 
    18.         for (int i = 0; i < 100; i++) { 
    19.              ImageAndText test=new ImageAndText("http://www.wangmeng.cn/images/logo.gif", "test"); 
    20.              ImageAndText test1=new ImageAndText("http://www.pfwx.com/files/article/image/0/54/54s.jpg", "test1"); 
    21.              ImageAndText test2=new ImageAndText("http://www.pfwx.com/files/article/image/0/4/4s.jpg","test2"); 
    22.              ImageAndText test3=new ImageAndText("http://www.pfwx.com/files/article/image/9/9760/9760s.jpg","test3"); 
    23.              ImageAndText test4=new ImageAndText("http://www.pfwx.com/files/article/image/3/3382/3382s.jpg","test4"); 
    24.              ImageAndText test5=new ImageAndText("http://www.pfwx.com/files/article/image/3/3237/3237s.jpg","test5"); 
    25.              dataArray.add(test); 
    26.              dataArray.add(test1); 
    27.              dataArray.add(test2);   
    28.              dataArray.add(test3);   
    29.              dataArray.add(test4);   
    30.              dataArray.add(test5);   
    31.               
    32.         } 
    33.         
    34.         ImageAndTextListAdapter adapter=new ImageAndTextListAdapter(this, dataArray, list); 
    35.         list.setAdapter(adapter); 
    36.          
    37.     } 
    package cn.wangmeng.test;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.ListView;
    
    public class AsyncListImage extends Activity {
    	private ListView list;
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            list=(ListView)findViewById(R.id.list);
            List<ImageAndText> dataArray=new ArrayList<ImageAndText>();
            for (int i = 0; i < 100; i++) {
            	 ImageAndText test=new ImageAndText("http://www.wangmeng.cn/images/logo.gif", "test");
                 ImageAndText test1=new ImageAndText("http://www.pfwx.com/files/article/image/0/54/54s.jpg", "test1");
                 ImageAndText test2=new ImageAndText("http://www.pfwx.com/files/article/image/0/4/4s.jpg","test2");
                 ImageAndText test3=new ImageAndText("http://www.pfwx.com/files/article/image/9/9760/9760s.jpg","test3");
                 ImageAndText test4=new ImageAndText("http://www.pfwx.com/files/article/image/3/3382/3382s.jpg","test4");
                 ImageAndText test5=new ImageAndText("http://www.pfwx.com/files/article/image/3/3237/3237s.jpg","test5");
                 dataArray.add(test);
                 dataArray.add(test1);
                 dataArray.add(test2);	
                 dataArray.add(test3);	
                 dataArray.add(test4);	
                 dataArray.add(test5);	
                 
    		}
           
            ImageAndTextListAdapter adapter=new ImageAndTextListAdapter(this, dataArray, list);
            list.setAdapter(adapter);
            
        }
    }

    2、ImageAndText.java

    1. package cn.wangmeng.test; 
    2.  
    3. public class ImageAndText { 
    4.         private String imageUrl; 
    5.         private String text; 
    6.  
    7.         public ImageAndText(String imageUrl, String text) { 
    8.             this.imageUrl = imageUrl; 
    9.             this.text = text; 
    10.         } 
    11.         public String getImageUrl() { 
    12.             return imageUrl; 
    13.         } 
    14.         public String getText() { 
    15.             return text; 
    16.         } 
    package cn.wangmeng.test;
    
    public class ImageAndText {
    	    private String imageUrl;
    	    private String text;
    
    	    public ImageAndText(String imageUrl, String text) {
    	        this.imageUrl = imageUrl;
    	        this.text = text;
    	    }
    	    public String getImageUrl() {
    	        return imageUrl;
    	    }
    	    public String getText() {
    	        return text;
    	    }
    }
    

    上面两个代码一块讲 1、ImageAndText类是用来存储要与XML绑定的图片地址和名字地址的。

    2、将所有的地址都放在一个List里面(dataArray),然后将其传入ImageAndTextListAdapter()函数中;可见这个ImageAndTextListAdapter()函数是根据传进去的dataArray生成对应的Adapter的

    3、然后将ImageAndTextListAdapter()返回的Adapter与listView绑定

    3、ImageAndTextListAdapter.java

    这是重写于baseAdapter的类,由于重写于baseAdapter,所以有几个必须重写的函数,getCount()、getItem()、getItemId()、getView(),我们先把总体代码写出来,只讲一个getView()函数,其实函数就不讲了,先着重说下getView()函数在什么时候被系统调用:

    getView()函数在什么时候被系统调用:

    注意一点是android系统在显示列表时,并不是把所有代表都显示出来,让你随便划,划到哪是哪;而是根据当前的在划到的ITEM,调用当前ITEM的getView()来显示它。

    全部代码:

    1. package cn.wangmeng.test; 
    2.  
    3. import java.util.ArrayList; 
    4. import java.util.List; 
    5.  
    6. import cn.wangmeng.test.AsyncImageLoader.ImageCallback; 
    7.  
    8. import android.app.Activity; 
    9. import android.graphics.drawable.Drawable; 
    10. import android.util.Log; 
    11. import android.view.LayoutInflater; 
    12. import android.view.View; 
    13. import android.view.ViewGroup; 
    14. import android.widget.ArrayAdapter; 
    15. import android.widget.BaseAdapter; 
    16. import android.widget.ImageView; 
    17. import android.widget.ListView; 
    18. import android.widget.TextView; 
    19.  
    20. public class ImageAndTextListAdapter extends BaseAdapter { 
    21.  
    22.         private LayoutInflater inflater; 
    23.         private ListView listView; 
    24.         private AsyncImageLoader asyncImageLoader; 
    25.  
    26.         private List<ImageAndText> dataArray=new ArrayList<ImageAndText>(); 
    27.  
    28.         public ImageAndTextListAdapter(Activity activity, List<ImageAndText> imageAndTexts, ListView listView) { 
    29.  
    30.             this.listView = listView; 
    31.             asyncImageLoader = new AsyncImageLoader(); 
    32.             inflater = activity.getLayoutInflater(); 
    33.             dataArray=imageAndTexts; 
    34.         } 
    35.          
    36.         @Override 
    37.         public int getCount() { 
    38.             // TODO Auto-generated method stub  
    39.             return dataArray.size(); 
    40.         } 
    41.         @Override 
    42.         public Object getItem(int position) { 
    43.             // TODO Auto-generated method stub  
    44.             if(position >= getCount()){ 
    45.                 return null; 
    46.             } 
    47.             return dataArray.get(position); 
    48.         } 
    49.         @Override 
    50.         public long getItemId(int position) { 
    51.             // TODO Auto-generated method stub  
    52.             return position; 
    53.         } 
    54.  
    55.         //不需要ViewHolder版,直接将ImageAndText与XML资源关联起来  
    56.         public View getView(int position, View convertView, ViewGroup parent) { 
    57.             if (convertView == null) { 
    58.                  convertView = inflater.inflate(R.layout.book_item_adapter, null); 
    59.             } 
    60.             convertView.setTag(position); 
    61.              
    62.             ImageAndText imageAndText = (ImageAndText) getItem(position); 
    63.             String imageUrl = imageAndText.getImageUrl(); 
    64.              
    65.             TextView textView =  (TextView) convertView.findViewById(R.id.sItemTitle);  
    66.             // 将XML视图项与用户输入的URL和文本在绑定  
    67.             textView.setText(imageAndText.getText());//加载TEXT  
    68.             ImageView iv = (ImageView) convertView.findViewById(R.id.sItemIcon); 
    69.             iv.setBackgroundResource(R.drawable.rc_item_bg);//在初始化时,先把背景图片设置成默认背景,  
    70.                                         //否则在下拉时会随机匹配背景,不美观  
    71.      
    72.             asyncImageLoader.loadDrawable(position,imageUrl, new ImageCallback() { 
    73.                 @Override 
    74.                 public void onImageLoad(Integer pos, Drawable drawable) { 
    75.                     View view = listView.findViewWithTag(pos); 
    76.                     if(view != null){ 
    77.                         ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon); 
    78.                         iv.setBackgroundDrawable(drawable); 
    79.                     } 
    80.                 } 
    81.                 //加载不成功的图片处理      
    82.                 @Override 
    83.                 public void onError(Integer pos) { 
    84.                     View view = listView.findViewWithTag(pos); 
    85.                     if(view != null){ 
    86.                         ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon); 
    87.                         iv.setBackgroundResource(R.drawable.rc_item_bg); 
    88.                     } 
    89.                 } 
    90.                  
    91.             }); 
    92.             return convertView; 
    93.         } 
    package cn.wangmeng.test;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import cn.wangmeng.test.AsyncImageLoader.ImageCallback;
    
    import android.app.Activity;
    import android.graphics.drawable.Drawable;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.BaseAdapter;
    import android.widget.ImageView;
    import android.widget.ListView;
    import android.widget.TextView;
    
    public class ImageAndTextListAdapter extends BaseAdapter {
    
    		private LayoutInflater inflater;
    	    private ListView listView;
    	    private AsyncImageLoader asyncImageLoader;
    
    	    private List<ImageAndText> dataArray=new ArrayList<ImageAndText>();
    
    	    public ImageAndTextListAdapter(Activity activity, List<ImageAndText> imageAndTexts, ListView listView) {
    
    	        this.listView = listView;
    	        asyncImageLoader = new AsyncImageLoader();
    	        inflater = activity.getLayoutInflater();
    	        dataArray=imageAndTexts;
    	    }
    	    
    		@Override
    		public int getCount() {
    			// TODO Auto-generated method stub
    			return dataArray.size();
    		}
    		@Override
    		public Object getItem(int position) {
    			// TODO Auto-generated method stub
    			if(position >= getCount()){
    				return null;
    			}
    			return dataArray.get(position);
    		}
    		@Override
    		public long getItemId(int position) {
    			// TODO Auto-generated method stub
    			return position;
    		}
    
    	    //不需要ViewHolder版,直接将ImageAndText与XML资源关联起来
    	    public View getView(int position, View convertView, ViewGroup parent) {
    	    	if (convertView == null) {
    	        	 convertView = inflater.inflate(R.layout.book_item_adapter, null);
    	        }
    	        convertView.setTag(position);
    	        
    	        ImageAndText imageAndText = (ImageAndText) getItem(position);
    	        String imageUrl = imageAndText.getImageUrl();
    	        
    	        TextView textView =  (TextView) convertView.findViewById(R.id.sItemTitle); 
    	        // 将XML视图项与用户输入的URL和文本在绑定
    	        textView.setText(imageAndText.getText());//加载TEXT
    	        ImageView iv = (ImageView) convertView.findViewById(R.id.sItemIcon);
    	        iv.setBackgroundResource(R.drawable.rc_item_bg);//在初始化时,先把背景图片设置成默认背景,
    	        							//否则在下拉时会随机匹配背景,不美观
    	
    	        asyncImageLoader.loadDrawable(position,imageUrl, new ImageCallback() {
    	        	@Override
    	    		public void onImageLoad(Integer pos, Drawable drawable) {
    	    			View view = listView.findViewWithTag(pos);
    	    			if(view != null){
    	    				ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
    	    				iv.setBackgroundDrawable(drawable);
    	    			}
    	    		}
    	        	//加载不成功的图片处理	
    				@Override
    				public void onError(Integer pos) {
    					View view = listView.findViewWithTag(pos);
    					if(view != null){
    						ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
    						iv.setBackgroundResource(R.drawable.rc_item_bg);
    					}
    				}
    	        	
    	        });
    	        return convertView;
    	    }
    }
    

    我们着重看getView()函数 1、看这段:

    1. if (convertView == null) { 
    2.      convertView = inflater.inflate(R.layout.book_item_adapter, null); 
    3. convertView.setTag(position); 
    4.  
    5. ImageAndText imageAndText = (ImageAndText) getItem(position); 
    6. String imageUrl = imageAndText.getImageUrl(); 
    7.  
    8. TextView textView =  (TextView) convertView.findViewById(R.id.sItemTitle);  
    9. // 将XML视图项与用户输入的URL和文本在绑定  
    10. textView.setText(imageAndText.getText());//加载TEXT  
    11. ImageView iv = (ImageView) convertView.findViewById(R.id.sItemIcon); 
    12. iv.setBackgroundResource(R.drawable.rc_item_bg); 
    if (convertView == null) {
    	 convertView = inflater.inflate(R.layout.book_item_adapter, null);
    }
    convertView.setTag(position);
    
    ImageAndText imageAndText = (ImageAndText) getItem(position);
    String imageUrl = imageAndText.getImageUrl();
    
    TextView textView =  (TextView) convertView.findViewById(R.id.sItemTitle); 
    // 将XML视图项与用户输入的URL和文本在绑定
    textView.setText(imageAndText.getText());//加载TEXT
    ImageView iv = (ImageView) convertView.findViewById(R.id.sItemIcon);
    iv.setBackgroundResource(R.drawable.rc_item_bg);

    这段代码没什么特别的就是将前面dataArray的信息与XML的元素项对应起来,并绑定,最关键的是下面这段,下面这个方法才是实现异步加载图片的关键:

    1. asyncImageLoader.loadDrawable(position,imageUrl, new ImageCallback() { 
    2.     @Override 
    3.     public void onImageLoad(Integer pos, Drawable drawable) { 
    4.         View view = listView.findViewWithTag(pos); 
    5.         if(view != null){ 
    6.             ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon); 
    7.             iv.setBackgroundDrawable(drawable); 
    8.         } 
    9.     } 
    10.     //加载不成功的图片处理      
    11.     @Override 
    12.     public void onError(Integer pos) { 
    13.         View view = listView.findViewWithTag(pos); 
    14.         if(view != null){ 
    15.             ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon); 
    16.             iv.setBackgroundResource(R.drawable.rc_item_bg); 
    17.         } 
    18.     } 
    19.      
    20. }); 
    asyncImageLoader.loadDrawable(position,imageUrl, new ImageCallback() {
    	@Override
    	public void onImageLoad(Integer pos, Drawable drawable) {
    		View view = listView.findViewWithTag(pos);
    		if(view != null){
    			ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
    			iv.setBackgroundDrawable(drawable);
    		}
    	}
    	//加载不成功的图片处理	
    	@Override
    	public void onError(Integer pos) {
    		View view = listView.findViewWithTag(pos);
    		if(view != null){
    			ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
    			iv.setBackgroundResource(R.drawable.rc_item_bg);
    		}
    	}
    	
    });

    这段代码的奇特之处在于,利用AsyncImageLoader类的实例(asyncImageLoader),调用方法loadDrawable()方法,就实现了加载后图像的绑定;好神奇,仔细看他是怎么做到的。这里先注意的有两点: (1)、传进去的参数,当前项的位置(position),当前图片的URL(imageUrl),一个名称为ImageCallback()接口函数;

    (2)、ImageCallback()接口函数里的两个被重写的函数onImageLoad()和onError()

    3、AsyncImageLoader.java

    从上面的讲解也应该能猜到这个类,主要的功能就是加载图片,然后成功后更新UI;

    先看全部代码,然后再逐步讲

    1. package cn.wangmeng.test; 
    2.  
    3. import java.io.IOException; 
    4. import java.io.InputStream; 
    5. import java.lang.ref.SoftReference; 
    6. import java.net.URL; 
    7. import java.util.HashMap; 
    8.  
    9. import android.graphics.drawable.Drawable; 
    10. import android.os.Handler; 
    11.  
    12. public class AsyncImageLoader { 
    13.     final Handler handler = new Handler(); 
    14.     private HashMap<String, SoftReference<Drawable>> imageCache; 
    15.     public AsyncImageLoader() { 
    16.         imageCache = new HashMap<String, SoftReference<Drawable>>();//图片缓存  
    17.     } 
    18.      
    19.     // 回调函数  
    20.     public interface ImageCallback { 
    21.         public void onImageLoad(Integer t, Drawable drawable); 
    22.         public void onError(Integer t); 
    23.     } 
    24.  
    25.     public Drawable loadDrawable(final Integer pos, final String imageUrl, 
    26.              final ImageCallback imageCallback) { 
    27.         new Thread() { 
    28.             @Override 
    29.             public void run() { 
    30.                  
    31.                 LoadImg(pos, imageUrl, imageCallback); 
    32.  
    33.             } 
    34.         }.start(); 
    35.         return null; 
    36.     }// loadDrawable---end  
    37.  
    38.     public void LoadImg(final Integer pos, final String imageUrl, 
    39.             final ImageCallback imageCallback) { 
    40.         // 首先判断是否在缓存中  
    41.         // 但有个问题是:ImageCache可能会越来越大,以至用户内存用光,所以要用SoftReference(弱引用)来实现  
    42.         if (imageCache.containsKey(imageUrl)) { 
    43.             SoftReference<Drawable> softReference = imageCache.get(imageUrl); 
    44.             final Drawable drawable = softReference.get(); 
    45.             if (drawable != null) { 
    46.                 handler.post(new Runnable() { 
    47.                     @Override 
    48.                     public void run() { 
    49.                         imageCallback.onImageLoad(pos, drawable); 
    50.                     } 
    51.                 }); 
    52.                 return; 
    53.             } 
    54.         } 
    55.         // 尝试从URL中加载  
    56.         try { 
    57.             final Drawable drawable = loadImageFromUrl(imageUrl); 
    58.             if (drawable != null) { 
    59.                 imageCache.put(imageUrl, new SoftReference<Drawable>(drawable)); 
    60.             } 
    61.             handler.post(new Runnable() { 
    62.                 @Override 
    63.                 public void run() { 
    64.                         imageCallback.onImageLoad(pos, drawable); 
    65.                 } 
    66.             }); 
    67.         } catch (IOException e) { 
    68.             handler.post(new Runnable() { 
    69.                 @Override 
    70.                 public void run() { 
    71.                     imageCallback.onError(pos); 
    72.                 } 
    73.             }); 
    74.             e.printStackTrace(); 
    75.         } 
    76.  
    77.     } 
    78.  
    79.     // 根据URL加载图片,如果出现错误throws IOException式的错误,以便在LoadImg中捕获,执行OnError()函数  
    80.     public static Drawable loadImageFromUrl(String url) throws IOException { 
    81.         URL m; 
    82.         InputStream i = null; 
    83.         m = new URL(url); 
    84.         i = (InputStream) m.getContent(); 
    85.         Drawable d = Drawable.createFromStream(i, "src"); 
    86.         return d; 
    87.     } 
    88.  
    package cn.wangmeng.test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.ref.SoftReference;
    import java.net.URL;
    import java.util.HashMap;
    
    import android.graphics.drawable.Drawable;
    import android.os.Handler;
    
    public class AsyncImageLoader {
    	final Handler handler = new Handler();
    	private HashMap<String, SoftReference<Drawable>> imageCache;
    	public AsyncImageLoader() {
    		imageCache = new HashMap<String, SoftReference<Drawable>>();//图片缓存
    	}
    	
    	// 回调函数
    	public interface ImageCallback {
    		public void onImageLoad(Integer t, Drawable drawable);
    		public void onError(Integer t);
    	}
    
    	public Drawable loadDrawable(final Integer pos, final String imageUrl,
    			 final ImageCallback imageCallback) {
    		new Thread() {
    			@Override
    			public void run() {
    				
    				LoadImg(pos, imageUrl, imageCallback);
    
    			}
    		}.start();
    		return null;
    	}// loadDrawable---end
    
    	public void LoadImg(final Integer pos, final String imageUrl,
    			final ImageCallback imageCallback) {
    		// 首先判断是否在缓存中
    		// 但有个问题是:ImageCache可能会越来越大,以至用户内存用光,所以要用SoftReference(弱引用)来实现
    		if (imageCache.containsKey(imageUrl)) {
    			SoftReference<Drawable> softReference = imageCache.get(imageUrl);
    			final Drawable drawable = softReference.get();
    			if (drawable != null) {
    				handler.post(new Runnable() {
    					@Override
    					public void run() {
    						imageCallback.onImageLoad(pos, drawable);
    					}
    				});
    				return;
    			}
    		}
    		// 尝试从URL中加载
    		try {
    			final Drawable drawable = loadImageFromUrl(imageUrl);
    			if (drawable != null) {
    				imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
    			}
    			handler.post(new Runnable() {
    				@Override
    				public void run() {
    						imageCallback.onImageLoad(pos, drawable);
    				}
    			});
    		} catch (IOException e) {
    			handler.post(new Runnable() {
    				@Override
    				public void run() {
    					imageCallback.onError(pos);
    				}
    			});
    			e.printStackTrace();
    		}
    
    	}
    
    	// 根据URL加载图片,如果出现错误throws IOException式的错误,以便在LoadImg中捕获,执行OnError()函数
    	public static Drawable loadImageFromUrl(String url) throws IOException {
    		URL m;
    		InputStream i = null;
    		m = new URL(url);
    		i = (InputStream) m.getContent();
    		Drawable d = Drawable.createFromStream(i, "src");
    		return d;
    	}
    
    }
    

    分别讲解 1、先看这段代码

    1. // 回调函数  
    2. public interface ImageCallback { 
    3.     public void onImageLoad(Integer t, Drawable drawable); 
    4.     public void onError(Integer t); 
    5.  
    6. public Drawable loadDrawable(final Integer pos, final String imageUrl, 
    7.          final ImageCallback imageCallback) { 
    8.     new Thread() { 
    9.         @Override 
    10.         public void run() { 
    11.              
    12.             LoadImg(pos, imageUrl, imageCallback); 
    13.  
    14.         } 
    15.     }.start(); 
    16.     return null; 
    17. }// loadDrawable---end 
    	// 回调函数
    	public interface ImageCallback {
    		public void onImageLoad(Integer t, Drawable drawable);
    		public void onError(Integer t);
    	}
    
    	public Drawable loadDrawable(final Integer pos, final String imageUrl,
    			 final ImageCallback imageCallback) {
    		new Thread() {
    			@Override
    			public void run() {
    				
    				LoadImg(pos, imageUrl, imageCallback);
    
    			}
    		}.start();
    		return null;
    	}// loadDrawable---end

    (1)首先注意,刚才我们调用的loadDrawable()函数,里面初始化并运行了一个线程,而这个线程的里面只有一个函数LoadImg(),对于这个函数下面我们具体讲,它的主要功能就是加载图片,然后更新UI (2)上面也看出了ImageCallback是一个接口,而里面的两个函数onImageLoad()和onError()在这里是没有具体实现的,那在哪里实现呢,当然是我们上面的ImageAndTextListAdapter.java里面了,等下我们具体会再讲。

    再往下看

    1. // 根据URL加载图片,如果出现错误throws IOException式的错误,以便在LoadImg中捕获,执行OnError()函数  
    2.     public static Drawable loadImageFromUrl(String url) throws IOException { 
    3.         URL m; 
    4.         InputStream i = null; 
    5.         m = new URL(url); 
    6.         i = (InputStream) m.getContent(); 
    7.         Drawable d = Drawable.createFromStream(i, "src"); 
    8.         return d; 
    9.     } 
    10.      
    11. public void LoadImg(final Integer pos, final String imageUrl, 
    12.         final ImageCallback imageCallback) { 
    13.     // 首先判断是否在缓存中  
    14.     // 但有个问题是:ImageCache可能会越来越大,以至用户内存用光,所以要用SoftReference(弱引用)来实现  
    15.     if (imageCache.containsKey(imageUrl)) { 
    16.         SoftReference<Drawable> softReference = imageCache.get(imageUrl); 
    17.         final Drawable drawable = softReference.get(); 
    18.         if (drawable != null) { 
    19.             handler.post(new Runnable() { 
    20.                 @Override 
    21.                 public void run() { 
    22.                     imageCallback.onImageLoad(pos, drawable); 
    23.                 } 
    24.             }); 
    25.             return; 
    26.         } 
    27.     } 
    28.     // 尝试从URL中加载  
    29.     try { 
    30.         final Drawable drawable = loadImageFromUrl(imageUrl); 
    31.         if (drawable != null) { 
    32.             imageCache.put(imageUrl, new SoftReference<Drawable>(drawable)); 
    33.         } 
    34.         handler.post(new Runnable() { 
    35.             @Override 
    36.             public void run() { 
    37.                     imageCallback.onImageLoad(pos, drawable); 
    38.             } 
    39.         }); 
    40.     } catch (IOException e) { 
    41.         handler.post(new Runnable() { 
    42.             @Override 
    43.             public void run() { 
    44.                 imageCallback.onError(pos); 
    45.             } 
    46.         }); 
    47.         e.printStackTrace(); 
    48.     } 
    49.  
    	// 根据URL加载图片,如果出现错误throws IOException式的错误,以便在LoadImg中捕获,执行OnError()函数
    		public static Drawable loadImageFromUrl(String url) throws IOException {
    			URL m;
    			InputStream i = null;
    			m = new URL(url);
    			i = (InputStream) m.getContent();
    			Drawable d = Drawable.createFromStream(i, "src");
    			return d;
    		}
    		
    	public void LoadImg(final Integer pos, final String imageUrl,
    			final ImageCallback imageCallback) {
    		// 首先判断是否在缓存中
    		// 但有个问题是:ImageCache可能会越来越大,以至用户内存用光,所以要用SoftReference(弱引用)来实现
    		if (imageCache.containsKey(imageUrl)) {
    			SoftReference<Drawable> softReference = imageCache.get(imageUrl);
    			final Drawable drawable = softReference.get();
    			if (drawable != null) {
    				handler.post(new Runnable() {
    					@Override
    					public void run() {
    						imageCallback.onImageLoad(pos, drawable);
    					}
    				});
    				return;
    			}
    		}
    		// 尝试从URL中加载
    		try {
    			final Drawable drawable = loadImageFromUrl(imageUrl);
    			if (drawable != null) {
    				imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
    			}
    			handler.post(new Runnable() {
    				@Override
    				public void run() {
    						imageCallback.onImageLoad(pos, drawable);
    				}
    			});
    		} catch (IOException e) {
    			handler.post(new Runnable() {
    				@Override
    				public void run() {
    					imageCallback.onError(pos);
    				}
    			});
    			e.printStackTrace();
    		}
    
    	}
    

    (1)、loadImageFromUrl()函数,就是根据URL到网上加载图片,然后返回图片流Drawable类型变量 (2)、对于LoadImg()我们再拆一下,先看如何在缓存中加载

    1. if (imageCache.containsKey(imageUrl)) { 
    2.     SoftReference<Drawable> softReference = imageCache.get(imageUrl); 
    3.     final Drawable drawable = softReference.get(); 
    4.     if (drawable != null) { 
    5.         handler.post(new Runnable() { 
    6.             @Override 
    7.             public void run() { 
    8.                 imageCallback.onImageLoad(pos, drawable); 
    9.             } 
    10.         }); 
    11.         return; 
    12.     } 
    		if (imageCache.containsKey(imageUrl)) {
    			SoftReference<Drawable> softReference = imageCache.get(imageUrl);
    			final Drawable drawable = softReference.get();
    			if (drawable != null) {
    				handler.post(new Runnable() {
    					@Override
    					public void run() {
    						imageCallback.onImageLoad(pos, drawable);
    					}
    				});
    				return;
    			}
    		}

    注意:

    1、在这里就已经得到了图像

    1. SoftReference<Drawable> softReference = imageCache.get(imageUrl); 
    2. final Drawable drawable = softReference.get(); 
    			SoftReference<Drawable> softReference = imageCache.get(imageUrl);
    			final Drawable drawable = softReference.get();

    2、得到图像之后就到了这段代码:

    1. if (drawable != null) { 
    2.     handler.post(new Runnable() { 
    3.         @Override 
    4.         public void run() { 
    5.             imageCallback.onImageLoad(pos, drawable); 
    6.         } 
    7.     }); 
    8.     return; 
    			if (drawable != null) {
    				handler.post(new Runnable() {
    					@Override
    					public void run() {
    						imageCallback.onImageLoad(pos, drawable);
    					}
    				});
    				return;
    			}

    当我们得到图像之后,调用imageCallback.onImageLoad(pos, drawable);来更新UI,由于我们再回来看看ImageAndTextListAdapter.java中的代码

    1. asyncImageLoader.loadDrawable(position,imageUrl, new ImageCallback() { 
    2.     @Override 
    3.     public void onImageLoad(Integer pos, Drawable drawable) { 
    4.         View view = listView.findViewWithTag(pos); 
    5.         if(view != null){ 
    6.             ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon); 
    7.             iv.setBackgroundDrawable(drawable); 
    8.         } 
    9.     } 
    10.      
    11. }); 
    asyncImageLoader.loadDrawable(position,imageUrl, new ImageCallback() {
    	@Override
    	public void onImageLoad(Integer pos, Drawable drawable) {
    		View view = listView.findViewWithTag(pos);
    		if(view != null){
    			ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
    			iv.setBackgroundDrawable(drawable);
    		}
    	}
    	
    });

    看到了吧,就是把得到的drawable与加载到UI中!!!!这就实现了回调

    OK,就到这吧,OnError()的原理一样,只不过是对程序没有加载到图片时应该怎么处理,其实就是当没有加载到图片时就是默认图片代替。
    下面给出源码:http://download.csdn.net/detail/harvic880925/6802241(不要分,仅供分享)

    请大家尊重作者板权,转载请标明出处:http://blog.csdn.net/harvic880925/article/details/17766027 ,谢谢!

  • 相关阅读:
    织梦插件开发
    yiic使用笔记
    yii2.0学习及变化比较(一)
    yii框架设计学习笔记(一)
    Maven生成可以直接运行的jar包的多种方式(转)
    Linux下查看CPU型号,内存大小,硬盘空间的命令(详解)
    从Google Earth 中下载三维模型
    Hadoop安装所遇问题及解决方法
    智慧家居体系结构
    .Net 数据库(SqlServer2008)的备份、还原
  • 原文地址:https://www.cnblogs.com/feijian/p/4190368.html
Copyright © 2011-2022 走看看