码迷,mamicode.com
首页 > 其他好文 > 详细

SoftReference+Thread进行图片加载(二)

时间:2015-08-21 23:20:24      阅读:208      评论:0      收藏:0      [点我收藏+]

标签:setonscrolllistener   softreference   synchronized   createfromstream   thread   

main.xml(先看主页面布局,界面很简单,只有一个ListView)

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

再看listView的每个item的布局(只有一个图片控件,和一个文本控件,尽量简单化)

book_item_adapter.xml

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="70.0dip"
    android:background="@drawable/item"
    android:drawingCacheQuality="high"
    android:minHeight="70.0dip"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/sItemIcon"
        android:layout_width="42.0dip"
        android:layout_height="54.0dip"
        android:layout_margin="10.0dip"
        android:background="@drawable/rc_item_bg"
        android:padding="2.0dip"
        android:scaleType="fitXY" />

    <TextView
        android:text="斗破苍穹"
        android:id="@+id/sItemTitle"
        android:layout_width="fill_parent"
        android:layout_height="30.0dip"
        android:layout_alignTop="@+id/sItemIcon"
        android:layout_toRightOf="@+id/sItemIcon"
        android:gravity="center_vertical"
        android:singleLine="true"
        android:textColor="#ffffff"
        android:textSize="18.0sp" />
</RelativeLayout>

将item里的控件封装实体类对象

ImageAndText(这个比较简单,分别对应item里面的2个控件,一个是图片,一个是文本)

package cn.wangmeng.test;

public class ImageAndText {
	    private String imageUrl;
	    private String text;

	    public ImageAndText(String imageUrl, String text) {
	        this.imageUrl = imageUrl;
	        this.text = text;
	    }
	    public String getImageUrl() {
	        return imageUrl;
	    }
	    public String getText() {
	        return text;
	    }
}

接下来看主页面布局(比较简单,就是获取listview,创建data数据源,创建适配器,设置适配器即可)

AsyncListImage

package cn.wangmeng.test;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;

public class AsyncListImage extends Activity {
	private ListView list;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //布局只是一个listView控件
        setContentView(R.layout.main);
        //listView
        list=(ListView)findViewById(R.id.list);
        //data
        List<ImageAndText> dataArray=new ArrayList<ImageAndText>();
        for (int i = 0; i < 100; i++) {
       	 ImageAndText test=new ImageAndText("http://www.wangmeng.cn/images/logo.gif", "test");
         ImageAndText test1=new ImageAndText("http://www.pfwx.com/files/article/image/0/54/54s.jpg", "test1");
         ImageAndText test2=new ImageAndText("http://www.pfwx.com/files/article/image/0/4/4s.jpg","test2");
         ImageAndText test3=new ImageAndText("http://www.pfwx.com/files/article/image/9/9760/9760s.jpg","test3");
         ImageAndText test4=new ImageAndText("http://www.pfwx.com/files/article/image/3/3382/3382s.jpg","test4");
         ImageAndText test5=new ImageAndText("http://www.pfwx.com/files/article/image/3/3237/3237s.jpg","test5");
         dataArray.add(test);
         dataArray.add(test1);
         dataArray.add(test2);	
         dataArray.add(test3);	
         dataArray.add(test4);	
         dataArray.add(test5);	
		}
       //adapter
        ImageAndTextListAdapter adapter=new ImageAndTextListAdapter(this, dataArray, list);
        //setAdapter
        list.setAdapter(adapter);
        
    }
}

接下来看适配器代码(注释有说明)

ImageAndTextListAdapter

package cn.wangmeng.test;

import java.util.ArrayList;
import java.util.List;
import cn.wangmeng.test.AsyncImageLoader.ImageCallback;

import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class ImageAndTextListAdapter extends BaseAdapter{

		private LayoutInflater inflater;
	    private ListView listView;
	    private AsyncImageLoader asyncImageLoader;
	    private List<ImageAndText> dataArray=new ArrayList<ImageAndText>();

	    public ImageAndTextListAdapter(Activity activity, List<ImageAndText> imageAndTexts, ListView listView) {

	        this.listView = listView;
	        asyncImageLoader = new AsyncImageLoader();
	        inflater = activity.getLayoutInflater();
	        dataArray=imageAndTexts;
	        //设置滑动事件的监听
	        listView.setOnScrollListener(onScrollListener);
	    }
	    
		@Override
		public int getCount() {
			return dataArray.size();
		}
		@Override
		public Object getItem(int position) {
			if(position >= getCount()){
				return null;
			}
			return dataArray.get(position);
		}
		@Override
		public long getItemId(int position) {
			return position;
		}
	    @Override
	    public View getView(int position, View convertView, ViewGroup parent) {
	    	 /**页面一旦加载,就获取可显示item的布局,并且设置tag,待滑动时候,复用布局*/  
	        if (convertView == null) {
	        	 convertView = inflater.inflate(R.layout.book_item_adapter, null);
	        }
	        convertView.setTag(position);
	        /** 
	         * 获取可见item的data数据 
	         */ 
	        ImageAndText imageAndText = (ImageAndText) getItem(position);
	        String imageUrl = imageAndText.getImageUrl();
	        //设置值  
	        TextView textView =  (TextView) convertView.findViewById(R.id.sItemTitle); 
	        textView.setText(imageAndText.getText());//加载TEXT
	        ImageView iv = (ImageView) convertView.findViewById(R.id.sItemIcon);
	        //一上来就先加载默认的图片  
	        iv.setBackgroundResource(R.drawable.rc_item_bg);
			
	        /** 
	         * 在加载默认的图片同时,也进行异步请求图片下载 
	         */  
	        asyncImageLoader.loadDrawable(position,imageUrl, new ImageCallback() {
	        	@Override
	    		public void onImageLoad(Integer pos, Drawable drawable) {
	        		//获取设置标记的视图  
	    			View view = listView.findViewWithTag(pos);
	    			if(view != null){
	    				ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
	    				iv.setBackgroundDrawable(drawable);
	    			}
	    		}
	        	//加载不成功的图片处理	
				@Override
				public void onError(Integer pos) {
					View view = listView.findViewWithTag(pos);
					if(view != null){
						ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
						iv.setBackgroundResource(R.drawable.rc_item_bg);
					}
				}
	        	
	        });
	        return convertView;
	    }
	    
	    public void loadImage(){
			int start = listView.getFirstVisiblePosition();
			int end =listView.getLastVisiblePosition();
			if(end >= getCount()){
				end = getCount() -1;
			}
			asyncImageLoader.setLoadLimit(start, end);
			asyncImageLoader.unlock();
		}
	    
	    AbsListView.OnScrollListener onScrollListener = new AbsListView.OnScrollListener() {
			
			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {
				switch (scrollState) {
					case AbsListView.OnScrollListener.SCROLL_STATE_FLING:
						asyncImageLoader.lock();	
						break;
					case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
						loadImage();	
						break;
					case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
						asyncImageLoader.lock();
						break;
		
					default:
						break;
				}
				
			}
			
			@Override
			public void onScroll(AbsListView view, int firstVisibleItem,
					int visibleItemCount, int totalItemCount) {
			}
		};


}

接下来看下载类(注释很清楚了)

AsyncImageLoader

package cn.wangmeng.test;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.util.HashMap;

import android.graphics.drawable.Drawable;
import android.os.Handler;

public class AsyncImageLoader {
	private Object lock = new Object();
	private boolean mAllowLoad = true;
	private boolean firstLoad = true;
	private int mStartLoadLimit = 0;
	private int mStopLoadLimit = 0;
	final Handler handler = new Handler();

	private HashMap<String, SoftReference<Drawable>> imageCache;

	// 设置需要加载图片的position(可显示的位置区域)
	public void setLoadLimit(int startLoadLimit, int stopLoadLimit) {
		if (startLoadLimit > stopLoadLimit) {
			return;
		}
		mStartLoadLimit = startLoadLimit;
		mStopLoadLimit = stopLoadLimit;
	}

	/**
	 * 枷锁--阻塞线程
	 */
	public void lock() {
		mAllowLoad = false;
		firstLoad = false;
	}

	/**
	 * 解锁--loadDrawable加载图片
	 */
	public void unlock() {
		mAllowLoad = true;
		synchronized (lock) {
			lock.notifyAll();
		}
	}

	/*******************************************************
	 * 构造器--初始化图片缓存(软引用)
	 */
	public AsyncImageLoader() {
		imageCache = new HashMap<String, SoftReference<Drawable>>();
	}

	/**
	 * 进行图片异步加载的方法 参数:pos,url,接口
	 */
	public Drawable loadDrawable(final Integer pos, final String imageUrl,
			final ImageCallback imageCallback) {
		new Thread() {
			@Override
			public void run() {
				/**
				 * 初始化时候, !mAllowLoad为false, 就开始阻塞线程
				 */
				if (!mAllowLoad) {// 先阻塞线程
					synchronized (lock) {// 加锁
						try {
							lock.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
				/**
				 * 界面一旦展现就会执行
				 */
				if (mAllowLoad && firstLoad) {
					LoadImg(pos, imageUrl, imageCallback);
				}
				/**
				 * 页面初始化展现,会执行这个方法 滑动暂停会执行该方法
				 */
				if (mAllowLoad && pos <= mStopLoadLimit
						&& pos >= mStartLoadLimit) {
					LoadImg(pos, imageUrl, imageCallback);
				}

			}
		}.start();
		return null;
	}

	public void LoadImg(final Integer pos, final String imageUrl,
			final ImageCallback imageCallback) {
		/**
		 * 首先先判断缓存中有没有,如果缓存中包含某个Key值, 就从缓存中获取某个url,得到软引用内存里面的对象
		 */
		if (imageCache.containsKey(imageUrl)) {
			SoftReference<Drawable> softReference = imageCache.get(imageUrl);
			final Drawable drawable = softReference.get();
			// 如果软引用里面的图片没有被回收,就进行页面加载即可
			if (drawable != null) {
				// 通过handler消息机制,在主线程进行更新ui即可
				handler.post(new Runnable() {
					@Override
					public void run() {
						if (mAllowLoad) {
							imageCallback.onImageLoad(pos, drawable);
						} else {
							imageCallback.onError(pos);
						}
					}
				});
				return;
			}
		}
		// 尝试从URL中加载
		try {
			final Drawable drawable = loadImageFromUrl(imageUrl);
			// 如果图片获取成功了
			if (drawable != null) {
				// 放到缓存中
				imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
			}
			// 通过handler消息机制,在主线程进行更新ui即可
			handler.post(new Runnable() {
				@Override
				public void run() {
					if (mAllowLoad) {
						imageCallback.onImageLoad(pos, drawable);
					}
				}
			});
		} catch (IOException e) {
			handler.post(new Runnable() {
				@Override
				public void run() {
					imageCallback.onError(pos);
				}
			});
			e.printStackTrace();
		}

	}

	// 根据URL加载图片,如果出现错误throws IOException式的错误,以便在LoadImg中捕获,执行OnError()函数
	public static Drawable loadImageFromUrl(String url) throws IOException {
		URL m;
		InputStream i = null;
		m = new URL(url);
		i = (InputStream) m.getContent();
		Drawable d = Drawable.createFromStream(i, "src");
		return d;
	}

	// 回调函数
	public interface ImageCallback {
		public void onImageLoad(Integer t, Drawable drawable);

		public void onError(Integer t);
	}

}



SoftReference+Thread进行图片加载(二)

标签:setonscrolllistener   softreference   synchronized   createfromstream   thread   

原文地址:http://blog.csdn.net/u013210620/article/details/47844471

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!