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

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>

 

时间: 2024-11-01 18:47:25

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

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

MainActivity如下: package com.example.testlistview; import java.util.ArrayList; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.widget.ListView; //解决的问题: //1 ListView异步加载网络图片 //2 ListView滑动时,图片错位 public c

Android实现Listview异步加载网络图片并动态更新的方法_Android

本文实例讲述了Android实现Listview异步加载网络图片并动态更新的方法.分享给大家供大家参考,具体如下: 应用实例:解析后台返回的数据,把每条都显示在ListView中,包括活动图片.店名.活动详情.地址.电话和距离等. 在布局文件中ListView的定义: <ListView android:id="@id/maplistview" android:background="@drawable/bg" android:layout_width=&qu

Android实现Listview异步加载网络图片并动态更新的方法

本文实例讲述了Android实现Listview异步加载网络图片并动态更新的方法.分享给大家供大家参考,具体如下: 应用实例:解析后台返回的数据,把每条都显示在ListView中,包括活动图片.店名.活动详情.地址.电话和距离等. 在布局文件中ListView的定义: <ListView android:id="@id/maplistview" android:background="@drawable/bg" android:layout_width=&qu

android开发中解决ListView异步加载图片错乱问题

 代码如下 复制代码 : import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.net.URLConnection; import android.content.Context; import android

解决Android ListView异步加载图片乱序问题

在Android所有系统自带的控件当中,ListView这个控件算是用法比较复杂的了,关键是用法复杂也就算了,它还经常会出现一些稀奇古怪的问题,让人非常头疼.比如说在ListView中加载图片,如果是同步加载图片倒还好,但是一旦使用异步加载图片那么问题就来了,这个问题我相信很多Android开发者都曾经遇到过,就是异步加载图片会出现错位乱序的情况.遇到这个问题时,不少人在网上搜索找到了相应的解决方案,但是真正深入理解这个问题出现的原因并对症解决的人恐怕还并不是很多.那么今天我们就来具体深入分析一

ListView异步加载图片(解决图片混淆)

代码下载地址: http://115.com/file/e75ks6jj#ImageLoader_test.zip        由于工作原因,很久没有写博客了,工作中经常遇到ListView异步加载图片的问题,国内的网站上查了N多资料,几乎没有一个可用的,最根本的图片混淆问题都没有得到充分地解决.我的这个例子是借鉴Google Code中的例子,删除了其中的没有必要的代码,完全可行.   该工程由ImageListActivity.ImageAdapter.ImageDownloader三个类

listview异步加载图片并防止错位

android listview 异步加载图片并防止错位 网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertView 但没有异步操作也不会有问题. 我简单分析一下: 当重用 convertView 时,最初一屏显示 7 条记录, getView 被调用 7 次,创建了 7 个 convertView. 当 Item1 划出屏幕, Item8 进入屏幕时,

Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案

Android ListView异步加载图片错位.重复.闪烁分析以及解决方案,具体问题分析以及解决方案请看下文. 我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如ListView上有100个Item,一屏只显示10个Item,我们知道getView()中convertView是用来复用View对象的,因为一个Item的对应一个View对象,而Ima

iOS开发swift版异步加载网络图片(带缓存和缺省图片)

iOS开发之swift版异步加载网络图片     与SDWebImage异步加载网络图片的功能相似,只是代码比较简单,功能没有SD的完善与强大,支持缺省添加图片,支持本地缓存.      异步加载图片的核心代码如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 5