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>