解决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>



 

相关文章
|
8月前
|
前端开发 算法
一个有趣的图片加载效果
一个有趣的图片加载效果
71 0
|
JSON 前端开发 Android开发
Lottie 动画里有图片?有动画效果但图片加载不出来?
Lottie 动画里有图片?有动画效果但图片加载不出来?
1495 0
|
前端开发 容器
Flutter中ListView加载图片数据的优化
在使用ListView懒加载模式时,当ListView的Item中有图片信息时,在快速滚动过程中会大量的浪费流量与内存,甚至会造成在滚动过程中页面的卡顿效果。 在这里提出优化方案,当开始滚动时不加载图片,滚动结束后再加载图片,这个优化方案实现的效果如下图所示,在快速滑动列表数据时,图片未加载,运行内存无明显波动。
Flutter中ListView加载图片数据的优化
RecyclerView的下拉刷新和加载更多 动画
下拉刷新和加载更多 1、https://github.com/jianghejie/XRecyclerView 2、http://blog.csdn.net/jabony/article/details/44780187   动画 1、https://github.
1912 0
|
XML 数据格式 Android开发
关于Drawable资源加载的相关问题
图片资源无外乎两种,一种是图片文件格式,一种是xml格式,在布局文件中引用当然没什么可说的,我们主要说下在代码中如何获得drawable资源 1、res/drawable目录下资源加载 使用R.
914 0
|
JavaScript Android开发 前端开发