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>