1. 程式人生 > >非同步載入圖片的例項程式碼2

非同步載入圖片的例項程式碼2

package cindy.android.test.synclistview;


import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Window;
import android.widget.Toast;

public abstract class AbstructCommonActivity extends Activity {

private MyHandler handler = new MyHandler();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
}

protected void handleOtherMessage(int flag){

}

public void sendMessage(int flag) {
handler.sendEmptyMessage(flag);
}

public void sendMessageDely(int flag,long delayMillis){
handler.sendEmptyMessageDelayed(flag, delayMillis);
}

public void showToast(String toast_message){
handler.toast_message = toast_message;
sendMessage(MyHandler.SHOW_STR_TOAST);
}

public void showToast(int res){
handler.toast_res = res;
sendMessage(MyHandler.SHOW_RES_TOAST);
}

private class MyHandler extends Handler {
public static final int SHOW_STR_TOAST = 0;
public static final int SHOW_RES_TOAST = 1;

private String toast_message=null;
private int toast_res;

@Override
public void handleMessage(Message msg) {
if (!Thread.currentThread().isInterrupted()) {
switch (msg.what) {
case SHOW_STR_TOAST:
Toast.makeText(getBaseContext(), toast_message, 1).show();
break;
case SHOW_RES_TOAST:
Toast.makeText(getBaseContext(), toast_res, 1).show();
break;
default:
handleOtherMessage(msg.what);
}
}
}


}
}


package cindy.android.test.synclistview;

import java.util.Vector;


import android.content.Context;
import android.graphics.drawable.Drawable;
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 BookItemAdapter extends BaseAdapter{

private LayoutInflater mInflater;
private Context mContext;
private Vector<BookModel> mModels = new Vector<BookModel>();
private ListView mListView;
SyncImageLoader syncImageLoader;

public BookItemAdapter(Context context,ListView listView){
mInflater = LayoutInflater.from(context);
syncImageLoader = new SyncImageLoader();
mContext = context;
mListView = listView;

mListView.setOnScrollListener(onScrollListener);
}


public void addBook(String book_name,String out_book_url,String out_book_pic){
BookModel model = new BookModel();
model.book_name =book_name;
model.out_book_url = out_book_url;
model.out_book_pic = out_book_pic;
mModels.add(model);
}

public void clean(){
mModels.clear();
}

@Override
public int getCount() {
// TODO Auto-generated method stub
return mModels.size();
}

@Override
public Object getItem(int position) {
if(position >= getCount()){
return null;
}
return mModels.get(position);
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = mInflater.inflate(R.layout.book_item_adapter, null);
}
BookModel model = mModels.get(position);
convertView.setTag(position);
ImageView iv = (ImageView) convertView.findViewById(R.id.sItemIcon);
TextView sItemTitle = (TextView) convertView.findViewById(R.id.sItemTitle);
TextView sItemInfo = (TextView) convertView.findViewById(R.id.sItemInfo);
sItemTitle.setText(model.book_name);
sItemInfo.setText(model.out_book_url);
iv.setBackgroundResource(R.drawable.rc_item_bg);
syncImageLoader.loadImage(position,model.out_book_pic,imageLoadListener);
return convertView;
}

SyncImageLoader.OnImageLoadListener imageLoadListener = new SyncImageLoader.OnImageLoadListener(){

@Override
public void onImageLoad(Integer t, Drawable drawable) {
//BookModel model = (BookModel) getItem(t);
View view = mListView.findViewWithTag(t);
if(view != null){
ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
iv.setBackgroundDrawable(drawable);
}
}
@Override
public void onError(Integer t) {
BookModel model = (BookModel) getItem(t);
View view = mListView.findViewWithTag(model);
if(view != null){
ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
iv.setBackgroundResource(R.drawable.rc_item_bg);
}
}

};

public void loadImage(){
int start = mListView.getFirstVisiblePosition();
int end =mListView.getLastVisiblePosition();
if(end >= getCount()){
end = getCount() -1;
}
syncImageLoader.setLoadLimit(start, end);
syncImageLoader.unlock();
}

AbsListView.OnScrollListener onScrollListener = new AbsListView.OnScrollListener() {

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case AbsListView.OnScrollListener.SCROLL_STATE_FLING:
DebugUtil.debug("SCROLL_STATE_FLING");
syncImageLoader.lock();
break;
case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
DebugUtil.debug("SCROLL_STATE_IDLE");
loadImage();
//loadImage();
break;
case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
syncImageLoader.lock();
break;

default:
break;
}

}

@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub

}
};
}


package cindy.android.test.synclistview;

public class BookModel {
public String book_id;
public String out_book_url;
public String author;
public String book_state_s;
public String leading_role;
public String update_time;
public String book_name;
public String out_book_pic;
public String sort_id;
public String last_update_section_title;
public String last_update_section_url;
public String introduction;
}


package cindy.android.test.synclistview;

import android.content.Context;
import android.util.Log;
import android.widget.Toast;

public class DebugUtil {
public static final String TAG = "DebugUtil";
public static final boolean DEBUG = true;

public static void toast(Context context,String content){
Toast.makeText(context, content, Toast.LENGTH_SHORT).show();
}

public static void debug(String tag,String msg){
if (DEBUG) {
Log.d(tag, msg);
}
}

public static void debug(String msg){
if (DEBUG) {
Log.d(TAG, msg);
}
}

public static void error(String tag,String error){
Log.e(tag, error);
}

public static void error(String error){
Log.e(TAG, error);
}
}


package cindy.android.test.synclistview;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class LoadStateView extends RelativeLayout{

ProgressBar progBar;

LinearLayout downLoadErrMsgBox;

TextView downLoadErrText;

Button btnListLoadErr;

public LoadStateView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}

@Override
protected void onFinishInflate() {
// TODO Auto-generated method stub
super.onFinishInflate();
progBar = (ProgressBar) findViewById(R.id.progBar);
downLoadErrMsgBox = (LinearLayout) findViewById(R.id.downLoadErrMsgBox);
downLoadErrText = (TextView) findViewById(R.id.downLoadErrText);
btnListLoadErr = (Button) findViewById(R.id.btnListLoadErr);
}

public void startLoad(){
downLoadErrMsgBox.setVisibility(View.GONE);
progBar.setVisibility(View.VISIBLE);
}

public void stopLoad(){
progBar.setVisibility(View.GONE);
}

public void showError(){
downLoadErrMsgBox.setVisibility(View.VISIBLE);
progBar.setVisibility(View.GONE);
}

public void showEmpty(){
downLoadErrMsgBox.setVisibility(View.VISIBLE);
progBar.setVisibility(View.GONE);
}

public void setOnReloadClickListener(OnClickListener onReloadClickListener){
btnListLoadErr.setOnClickListener(onReloadClickListener);
}
}


package cindy.android.test.synclistview;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
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.Environment;
import android.os.Handler;

public class SyncImageLoader {

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 = new HashMap<String, SoftReference<Drawable>>();

public interface OnImageLoadListener {
public void onImageLoad(Integer t, Drawable drawable);
public void onError(Integer t);
}

public void setLoadLimit(int startLoadLimit,int stopLoadLimit){
if(startLoadLimit > stopLoadLimit){
return;
}
mStartLoadLimit = startLoadLimit;
mStopLoadLimit = stopLoadLimit;
}

public void restore(){
mAllowLoad = true;
firstLoad = true;
}

public void lock(){
mAllowLoad = false;
firstLoad = false;
}

public void unlock(){
mAllowLoad = true;
synchronized (lock) {
lock.notifyAll();
}
}

public void loadImage(Integer t, String imageUrl,
OnImageLoadListener listener) {
final OnImageLoadListener mListener = listener;
final String mImageUrl = imageUrl;
final Integer mt = t;

new Thread(new Runnable() {

@Override
public void run() {
if(!mAllowLoad){
DebugUtil.debug("prepare to load");
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

if(mAllowLoad && firstLoad){
loadImage(mImageUrl, mt, mListener);
}

if(mAllowLoad && mt <= mStopLoadLimit && mt >= mStartLoadLimit){
loadImage(mImageUrl, mt, mListener);
}
}

}).start();
}

private void loadImage(final String mImageUrl,final Integer mt,final OnImageLoadListener mListener){

if (imageCache.containsKey(mImageUrl)) {
SoftReference<Drawable> softReference = imageCache.get(mImageUrl);
final Drawable d = softReference.get();
if (d != null) {
handler.post(new Runnable() {
@Override
public void run() {
if(mAllowLoad){
mListener.onImageLoad(mt, d);
}
}
});
return;
}
}
try {
final Drawable d = loadImageFromUrl(mImageUrl);
if(d != null){
imageCache.put(mImageUrl, new SoftReference<Drawable>(d));
}
handler.post(new Runnable() {
@Override
public void run() {
if(mAllowLoad){
mListener.onImageLoad(mt, d);
}
}
});
} catch (IOException e) {
handler.post(new Runnable() {
@Override
public void run() {
mListener.onError(mt);
}
});
e.printStackTrace();
}
}

public static Drawable loadImageFromUrl(String url) throws IOException {
DebugUtil.debug(url);
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
File f = new File(Environment.getExternalStorageDirectory()+"/TestSyncListView/"+MD5.getMD5(url));
if(f.exists()){
FileInputStream fis = new FileInputStream(f);
Drawable d = Drawable.createFromStream(fis, "src");
return d;
}
URL m = new URL(url);
InputStream i = (InputStream) m.getContent();
DataInputStream in = new DataInputStream(i);
FileOutputStream out = new FileOutputStream(f);
byte[] buffer = new byte[1024];
int byteread=0;
while ((byteread = in.read(buffer)) != -1) {
out.write(buffer, 0, byteread);
}
in.close();
out.close();
Drawable d = Drawable.createFromStream(i, "src");
return loadImageFromUrl(url);
}else{
URL m = new URL(url);
InputStream i = (InputStream) m.getContent();
Drawable d = Drawable.createFromStream(i, "src");
return d;
}

}
}


package cindy.android.test.synclistview;


import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;

public class TestListViewActivity extends AbstructCommonActivity
implements AdapterView.OnItemClickListener{

ListView viewBookList;

BookItemAdapter adapter;

//ViewGroup listFolder;

LoadStateView loadStateView;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
viewBookList = (ListView) findViewById(R.id.viewBookList);
adapter = new BookItemAdapter(this,viewBookList);
loadStateView = (LoadStateView) findViewById(R.id.downloadStatusBox);

loadStateView.setOnReloadClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
reload();
}
});
//listFolder = (ViewGroup) getLayoutInflater().inflate(R.layout.load_more, null);
//viewBookList.addFooterView(listFolder);
viewBookList.setAdapter(adapter);
viewBookList.setOnItemClickListener(this);
reload();
}

private void reload(){
adapter.clean();
loadStateView.startLoad();
new Thread(new Runnable(){
@Override
public void run() {
try {
Thread.sleep(2*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
loadDate();
sendMessage(REFRESH_LIST);
//sendMessageDely(LOAD_IMAGE, 500);
}
}).start();
}

public void loadDate(){
for(int i=0;i<10;i++){
adapter.addBook("吞噬星空"+i,
"http://www.pfwx.com/bookinfo/11/11000.html",
"http://www.pfwx.com/files/article/image/11/11000/11000s.jpg");

adapter.addBook("仙逆"+i,
"http://www.pfwx.com/bookinfo/9/9760.html",
"http://www.pfwx.com/files/article/image/9/9760/9760s.jpg");

adapter.addBook("武動乾坤"+i,
"http://www.pfwx.com/bookinfo/13/13939.html",
"http://www.pfwx.com/files/article/image/13/13939/13939s.jpg");

adapter.addBook("凡人修仙傳"+i,
"http://www.pfwx.com/bookinfo/3/3237.html",
"http://www.pfwx.com/files/article/image/3/3237/3237s.jpg");

adapter.addBook("遮天"+i,
"http://www.pfwx.com/bookinfo/11/11381.html",
"http://www.pfwx.com/files/article/image/11/11381/11381s.jpg");
}
}

@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {

}

private static final int REFRESH_LIST = 0x10001;
private static final int SHOW_LOAD_STATE_VIEW = 0x10003;
private static final int HIDE_LOAD_STATE_VIEW = 0x10004;

@Override
protected void handleOtherMessage(int flag) {
switch (flag) {
case REFRESH_LIST:
adapter.notifyDataSetChanged();
loadStateView.stopLoad();
if(adapter.getCount() == 0){
loadStateView.showEmpty();
}
break;
case SHOW_LOAD_STATE_VIEW:
loadStateView.startLoad();
break;
case HIDE_LOAD_STATE_VIEW:
loadStateView.stopLoad();
break;

default:
break;
}
}

}