开发者社区> 小弟的谷哥> 正文

解决ListView异步加载网络图片的各种问题(二)

简介: MainActivity如下: package lee.listviewimage; import java.util.ArrayList; import java.
+关注继续查看

MainActivity如下:

package lee.listviewimage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lee.listviewimage.R;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleAdapter;
//解决的问题:
//1 ListView异步加载网络图片
//2 ListView滑动时,图片错位
public class MainActivity extends Activity {
    ListView listView;
    List<Map<String, Object>> arrayList; 
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        setContentView(R.layout.main);
        listView = (ListView) findViewById(R.id.listView);
        arrayList = new ArrayList<Map<String, Object>>();

        Map<String, Object> tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title111");
        tempHashMap.put("info", "111111");
        tempHashMap.put("img", "http://tb.himg.baidu.com/sys/portrait/item/d71e5a30323837797979d300");
        arrayList.add(tempHashMap);
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://img.baidu.com/img/post-jg.gif");
        arrayList.add(tempHashMap);
      
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://lh5.ggpht.com/_mrb7w4gF8Ds/TCpetKSqM1I/AAAAAAAAD2c/Qef6Gsqf12Y/s144-c/_DSC4374%20copy.jpg");
        arrayList.add(tempHashMap);
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://lh5.ggpht.com/_Z6tbBnE-swM/TB0CryLkiLI/AAAAAAAAVSo/n6B78hsDUz4/s144-c/_DSC3454.jpg");
        arrayList.add(tempHashMap);
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://lh3.ggpht.com/_GEnSvSHk4iE/TDSfmyCfn0I/AAAAAAAAF8Y/cqmhEoxbwys/s144-c/_MG_3675.jpg");
        arrayList.add(tempHashMap);
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://lh6.ggpht.com/_Nsxc889y6hY/TBp7jfx-cgI/AAAAAAAAHAg/Rr7jX44r2Gc/s144-c/IMGP9775a.jpg");
        arrayList.add(tempHashMap);
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://lh3.ggpht.com/_lLj6go_T1CQ/TCD8PW09KBI/AAAAAAAAQdc/AqmOJ7eg5ig/s144-c/Juvenile%20Gannet%20despute.jpg");
        arrayList.add(tempHashMap);
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://lh6.ggpht.com/_ZN5zQnkI67I/TCFFZaJHDnI/AAAAAAAABVk/YoUbDQHJRdo/s144-c/P9250508.JPG");
        arrayList.add(tempHashMap);

        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://lh6.ggpht.com/_lnDTHoDrJ_Y/TBvKsJ9qHtI/AAAAAAAAG6g/Zll2zGvrm9c/s144-c/000007.JPG");
        arrayList.add(tempHashMap);
        
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://info-database.csdn.net/Upload/2012-10-08/zazhi-210-90-1008.jpg");
        arrayList.add(tempHashMap);
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://images.csdn.net/20121119/20111211223655841.jpg");
        arrayList.add(tempHashMap);
		
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://csdnimg.cn/www/images/pic_foot_report110.png");
        arrayList.add(tempHashMap);
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://images.csdn.net/20121119/20120619174604972.jpg");
        arrayList.add(tempHashMap);
        

        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://images.csdn.net/20121018/zazhi-68-78-1018.jpg");
        arrayList.add(tempHashMap);
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://csdnimg.cn/www/images/pic_foot_report.png");
        arrayList.add(tempHashMap);
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://www.iteye.com/upload/logo/blog_wiki/711943/3a7f0290-47e6-3d62-8845-49735bc19a96.jpg?1343020143");
        arrayList.add(tempHashMap);
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://www.iteye.com/upload/logo/user/731519/c828deb2-5350-3fc7-83e7-b0eaa047d804-thumb.jpg?1346417059");
        arrayList.add(tempHashMap);
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://www.iteye.com/upload/logo/user/766328/b7d5f98d-f682-3d54-b697-6b9bacbcd534-thumb.jpg?1352965075");
        arrayList.add(tempHashMap);
        
        tempHashMap = new HashMap<String, Object>();
        tempHashMap.put("title", "title222");
        tempHashMap.put("info", "222222");
        tempHashMap.put("img", "http://www.iteye.com/upload/logo/user/40888/c82ef195-e561-3ac1-8714-a905052eae6d-thumb.jpg?1236834197");
        arrayList.add(tempHashMap);
        

        //利用此binder对象为ListViewItem中的小各个小控件绑定数据.此例子中未操作
        //注意:setViewValue方法的返回值很重要
        //即:bound=binder.setViewValue(everyViewOfThisHolder, data, textRepresentation);
        //一般的思路:
        //若此处返回false表示在TestSimpleAdapter里面继续对每个item进行数据的绑定.
        //若此处返回true表示在TestSimpleAdapter里面需要再对每个item进行数据的绑定
        //当然具体情况还是视具体的业务逻辑而定
        SimpleAdapter.ViewBinder binder = new SimpleAdapter.ViewBinder() {	
			@Override
			public boolean setViewValue(View view, Object data,String textRepresentation) {
				return false;
			}
		};
		 //listView原理http://www.xuanyusong.com/archives/1252
		  TestSimpleAdapter adapter = new TestSimpleAdapter(
		    		this,arrayList, R.layout.listviewitem, 
		    		new String[] {"title", "info", "img" }, 
		    		new int[] {R.id.title, R.id.info,R.id.imageView
		        },binder);
		//为此adapter设置ViewBinder
        adapter.setViewBinder(binder);
        listView.setAdapter(adapter);
	}    
}


自定义SimpleAdapter如下:

package lee.listviewimage;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Checkable;
import android.widget.ImageView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

public class TestSimpleAdapter extends SimpleAdapter {
    private AsyncImageLoader imageLoader = new AsyncImageLoader();
    //按照ListViewItem在ListView中的位置保存了此ListViewItem对应的View
    private Map<Integer, View> allItemsViewHashMap = new HashMap<Integer, View>();
    private LayoutInflater mInflater;
    private ViewBinder mViewBinder;
    private List<? extends Map<String, ?>> mData;
    private int mResource;			
    private String[] mFrom;				
    private int[] mTo;	
    
    //构造方法
    public TestSimpleAdapter(Context context, List<? extends Map<String, ?>> data,int resource, String[] from, int[] to,ViewBinder binder) {
        super(context, data, resource, from, to);
        mData = data;
        mResource = resource;
        mFrom = from;
        mTo = to;
        mViewBinder=binder;
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    	
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
          return createViewFromResource(position, convertView, parent, mResource);
    }

 
    private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource) {
        View everyItemView = this.allItemsViewHashMap.get(position);            
        if (everyItemView == null) {
            everyItemView = mInflater.inflate(resource, null);
            final int[] to = mTo;
            final int count = to.length;
            final View[] allPartsOfThisItem = new View[count];
            //将此Item中的所有子View存放在allPartsOfThisItem中
            for (int i = 0; i < count; i++) {
                allPartsOfThisItem[i] = everyItemView.findViewById(to[i]);
            }
            //给此itemView设置Tag!!!
            everyItemView.setTag(allPartsOfThisItem);
            //调用bindView.注意查看SimpleAdapter源码中也有这个方法.名字都一样
            //上一句setTag了,那么按照以往BaseAdapter的做法
            //后面就该为此item中的各个小控件赋值了,即在bindView中进行
            bindView(position, everyItemView);
            //将此Item对应的View保存到HashMap中
            allItemsViewHashMap.put(position, everyItemView);
        }
        return everyItemView;
    }
    
    //每个Item都会调用此方法
    //ViewBinder相当于设定了绑定规则
    //类似于BaseAdapter中getView中后半部分为此Item各控件赋值的处理
    @SuppressWarnings("unchecked")
    private void bindView(int position, View view) {
    	//取出listView中对应于此item中的数据(对应一个HashMap)
        final Map everyHashMapForAItem = mData.get(position);
        if (everyHashMapForAItem == null) {
            return;
        }  
        final ViewBinder binder = mViewBinder;
        //bindView方法的第二参数,即为ListView的每个item
        //得到ListView的每个item的Tag
        //并将里面获取的所有小组件保存至allMinViews中
        final View[] allMinViews = (View[]) view.getTag();
        final String[] from = mFrom;
        final int[] to = mTo;
        final int count = to.length;

        for (int i = 0; i < count; i++) {
            final View everyViewOfThisHolder = allMinViews[i];
            if (everyViewOfThisHolder != null) {
            	//以from[i]为键从HashMap中取出对应的值  
                final Object data = everyHashMapForAItem.get(from[i]);
                String textRepresentation = null;

                if (data == null) {
                	textRepresentation = "";
                } else {
                	//参考binder.setViewValue方法的文档.可知textRepresentation
                	//一般为data.toString
                	textRepresentation = data.toString();
                }

                boolean bound = false;
                if (binder != null) {	
                	//重要参考资料:
                	//http://www.cnblogs.com/angeldevil/archive/2012/04/05/2432615.html
                	//http://www.cnblogs.com/over140/archive/2010/12/15/1906303.html
                	//该方法的作用:判断在MainActivity中binder的方法setViewValue的返回值
                    bound = binder.setViewValue(everyViewOfThisHolder, data, textRepresentation);
                }

                if (!bound) {
                    if (everyViewOfThisHolder instanceof Checkable) {
                        if (data instanceof Boolean) {
                            ((Checkable) everyViewOfThisHolder).setChecked((Boolean) data);
                        } else {
                            throw new IllegalStateException(everyViewOfThisHolder.getClass().getName()+
                            		" should be bound to a Boolean, not a "+ data.getClass());
                        }
                    } else if (everyViewOfThisHolder instanceof TextView) {
                    	//setViewText 是simpleAdapter的方法
                        setViewText((TextView) everyViewOfThisHolder, textRepresentation);
                    } else if (everyViewOfThisHolder instanceof ImageView) {
                        if (data instanceof Integer) {
                        	//setViewImage是simpleAdapter的方法
                        	//调用setImageToImageView1也一样
                            setViewImage((ImageView) everyViewOfThisHolder, (Integer) data);
                        } else {
//                        	if (position==1) {
//								v.setVisibility(android.view.View.GONE);
//							} else {
//								setViewImage((ImageView) v, urlText);
//							}
                        	setImageToImageView2((ImageView) everyViewOfThisHolder, textRepresentation);
                        }
                    } else {
                        throw new IllegalStateException(everyViewOfThisHolder.getClass().getName()+ 
                        		" is not a "+ " view that can be bounds by this SimpleAdapter");
                    }
                }
            }
        }
    }

     //ImageView及图片的资源id
     public void setImageToImageView1(ImageView v, int value) {
         v.setImageResource(value);
     }
    //ImageView及图片的URL
     public void setImageToImageView2(final ImageView iamgeView, String url) {
         imageLoader.loadDrawable(url, new AsyncImageLoader.ImageCallback() {
             public void imageLoaded(Drawable imageDrawable, String imageUrl) {
                 if(imageDrawable!=null && imageDrawable.getIntrinsicWidth()>0 ) {
                	 iamgeView.setImageDrawable(imageDrawable);
                 }
             }
         });
     }

 } 


异步加载网络图片,方法如下:

package lee.listviewimage;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
public class AsyncImageLoader {
    private Map<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
    public Drawable loadDrawable(final String imageUrl,final ImageCallback callback) {
    	if (imageCache.containsKey(imageUrl)) {
            SoftReference<Drawable> softReference = imageCache.get(imageUrl);
            if (softReference.get() != null) {
                return softReference.get();
            }
        }
        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                callback.imageLoaded((Drawable) msg.obj, imageUrl);
            }
        };
     
        new Thread() {
            public void run() {
            	//从网络上获取图片
                Drawable drawable = loadImageFromUrl(imageUrl);
                imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
                handler.sendMessage(handler.obtainMessage(0, drawable));
            };
        }.start();
        
        return null;
    }

    protected Drawable loadImageFromUrl(String imageUrl) {
        try {
            return Drawable.createFromStream(new URL(imageUrl).openStream(),"src");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    //定义一个回调接口
    public interface ImageCallback {
        public void imageLoaded(Drawable imageDrawable, String imageUrl);
    }
    
}


listviewitem.xml如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="50dip">

    <ImageView 
        android:id="@+id/imageView"
        android:layout_width="50dip"
        android:layout_height="50dip" 
        android:scaleType="fitXY" 
        android:src="@drawable/icon"    
        android:layout_margin="5px"/>
    <LinearLayout 
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        
        <TextView 
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#FFFFFFFF"
            android:textSize="22px" 
            />
        
        <TextView 
        	android:id="@+id/info"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#FFFFFFFF"
            android:textSize="13px" />
    </LinearLayout>

</LinearLayout>

main.xml如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent">

<ListView 
	android:id="@+id/listView"       
	android:layout_width="fill_parent" 
	android:layout_height="wrap_content"
	android:choiceMode="singleChoice" />		    
</LinearLayout>



 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
WebView加载页面的两种方式——网络页面和本地页面
WebView加载页面的两种方式 一、加载网络页面   加载网络页面,是最简单的一种方式,只需要传入http的URL就可以,实现WebView加载网络页面 代码如下图: 二、加载本地页面   1、加载assets目录下的HTML页面: 加载assets目录的页面,大多数可以用来做页面数据的存储打包...
1345 0
LTE小小区技术需求背景 | 带你读《5G UDN(超密集网络)技术详解》之八
微博、微信、微视频、微创新……全球诸多领域都已进入到所谓 的“微时代”。4G LTE 对应着智能终端和移动业务应用迅猛发 展的大时代,而 LTE 微蜂窝和小小区技术在此背景下,应运而生,这 为之后 5G 更强的微蜂窝和小小区技术奠定和积累了重要的发展基础 和经验。
1126 0
[Android]ListView的Adapter.getView()方法中延迟加载图片的优化
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4139998.html   举个例子吧,以好友列表为例 ListView中每个Item表示一个好友,每个好友中都有一个头像,需要从服务端加载到本地,然后显示在item中。
784 0
实用技巧:使用 jQuery 异步加载 JavaScript 脚本
  JavaScript 加载器在 Web 开发中是非常强大和有用的工具。目前流行的几个加载器,像 curljs、LABjs 和 RequireJS 使用都很广泛。他们功能强大的,但有些情况下可以有更简单的方案。
905 0
+关注
小弟的谷哥
welcome
766
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载