生活随笔
收集整理的這篇文章主要介紹了
异步加载图片(二)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言:上篇《異步加載圖片(一)》講解了怎樣實現異步加載圖片,由于篇幅已經比較長就另開一篇講解如何實現在用戶滑動時停止加載圖片,在停劃時繼續加載,這里我只貼出在上篇的基礎上更改的部分,并加以講解,對于完整的代碼參照源碼;
一、ImageAndTextListAdapter.java
先看完整代碼,然后再講更改的部分
[java] view plaincopy
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)?{??????????????if?(convertView?==?null)?{???????????????????convertView?=?inflater.inflate(R.layout.book_item_adapter,?null);??????????????}??????????????convertView.setTag(position);????????????????????????????ImageAndText?imageAndText?=?(ImageAndText)?getItem(position);??????????????String?imageUrl?=?imageAndText.getImageUrl();????????????????????????????TextView?textView?=??(TextView)?convertView.findViewById(R.id.sItemTitle);?????????????????????????????textView.setText(imageAndText.getText());??????????????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:??????????????????????????Log.v("msg",?"SCROLL_STATE_FLING----lock");??????????????????????????asyncImageLoader.lock();??????????????????????????????break;??????????????????????case?AbsListView.OnScrollListener.SCROLL_STATE_IDLE:??????????????????????????Log.v("msg",?"SCROLL停了---加載");??????????????????????????loadImage();????????????????????????????????????????????????????????break;??????????????????????case?AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:??????????????????????????Log.d("msg",?"SCROLL_STATE_TOUCH_SCROLL----lock");??????????????????????????asyncImageLoader.lock();??????????????????????????break;????????????????????????????????default:??????????????????????????break;??????????????????}????????????????????????????????}????????????????????????????@Override??????????????public?void?onScroll(AbsListView?view,?int?firstVisibleItem,??????????????????????int?visibleItemCount,?int?totalItemCount)?{??????????????????????????????????????????????????}??????????};??????}??
這里的代碼較上篇增加了一個ListView的滑動監聽器(AbsListView.OnScrollListener),然后在滑動的時候調用asyncImageLoader.lock();將其鎖定,也就是利用互斥將線程阻塞;在用戶停劃的時候,調用loadImage();函數將線程喚醒;
這里有幾個函數是AsyncImageLoader類里實現的函數:lock()----實現線程阻塞;unlock()------解除線程阻塞;setLoadLimit(start, end)-----首先找到列表中顯示的ITEM的上限和下限;loadImage()的功能就是先找到列表中在顯示區域中的ITEM的上限POS和下限POS,然后只喚醒這幾個線程,對于不在顯示區域的線程仍然保持阻止;
二、AsyncImageLoader.java
先看完整代碼:
[java] view plaincopy
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;????????public?AsyncImageLoader()?{??????????imageCache?=?new?HashMap<String,?SoftReference<Drawable>>();??????}????????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?Drawable?loadDrawable(final?Integer?pos,?final?String?imageUrl,???????????????final?ImageCallback?imageCallback)?{??????????new?Thread()?{??????????????@Override??????????????public?void?run()?{??????????????????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)?{??????????????????????????????if?(imageCache.containsKey(imageUrl))?{??????????????SoftReference<Drawable>?softReference?=?imageCache.get(imageUrl);??????????????final?Drawable?drawable?=?softReference.get();??????????????if?(drawable?!=?null)?{??????????????????handler.post(new?Runnable()?{??????????????????????@Override??????????????????????public?void?run()?{??????????????????????????if?(mAllowLoad)?{??????????????????????????????imageCallback.onImageLoad(pos,?drawable);??????????????????????????}else?{??????????????????????????????imageCallback.onError(pos);??????????????????????????}??????????????????????}??????????????????});??????????????????return;??????????????}??????????}????????????????????try?{??????????????final?Drawable?drawable?=?loadImageFromUrl(imageUrl);??????????????if?(drawable?!=?null)?{??????????????????imageCache.put(imageUrl,?new?SoftReference<Drawable>(drawable));??????????????}??????????????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();??????????}????????}??????????????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);??????}????}??
1、先看關鍵部分loadDrawable()函數
[java] view plaincopy
public?Drawable?loadDrawable(final?Integer?pos,?final?String?imageUrl,???????????final?ImageCallback?imageCallback)?{??????new?Thread()?{??????????@Override??????????public?void?run()?{??????????????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;??}??
這里較上回的不同點在于加了鎖---synchronized (lock);即如果用戶不讓加載的話,就利用synchronized (lock)和lock.wait()將線程阻塞,如果ITEM在加載范圍內,就利用下面的LoadImg()函數進行加載;
然后剩下的幾個不同點就是加載ITEM范圍限制的設定和加鎖解鎖的函數了;
[java] view plaincopy
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();??????}??}??
這幾個函數比較好理解,就不講了;
這里就實現了所有的功能,這里主要參考了這兩篇文章,在最后給出,感謝原作者的無私奉獻!
《又優化了一個Android ListView異步加載圖片》:http://www.iteye.com/topic/1118828
《又優化了一個Android ListView異步加載圖片(續)》:http://www.iteye.com/topic/1127914
對于作者的續篇,為了解決這里的開的線程太多的問題,將所有的線程整合成一個線程,這樣一嘗試,加載速度明顯慢了好多,其實可以利用信號量的原理,同時開幾個線程或者線程池,本人也沒那個能力將其改成線程池,本想利用AsyncTask來重新實現,因為AsyncTask使用的線程池,奈何技術不到位,實現不了……,只能再等高人去優化了。
源碼地址:http://download.csdn.net/detail/harvic880925/6802321
請大家尊重原創者版權,轉載請標明出處:
http://blog.csdn.net/harvic880925/article/details/17782063
? ,謝謝!!!!!!
總結
以上是生活随笔為你收集整理的异步加载图片(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。