日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

异步加载图片(二)

發布時間:2025/6/15 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 异步加载图片(二) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:上篇《異步加載圖片(一)》講解了怎樣實現異步加載圖片,由于篇幅已經比較長就另開一篇講解如何實現在用戶滑動時停止加載圖片,在停劃時繼續加載,這里我只貼出在上篇的基礎上更改的部分,并加以講解,對于完整的代碼參照源碼;

一、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()?{??
  • ????????????//?TODO?Auto-generated?method?stub??
  • ????????????return?dataArray.size();??
  • ????????}??
  • ????????@Override??
  • ????????public?Object?getItem(int?position)?{??
  • ????????????//?TODO?Auto-generated?method?stub??
  • ????????????if(position?>=?getCount()){??
  • ????????????????return?null;??
  • ????????????}??
  • ????????????return?dataArray.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?=?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);???
  • ????????????//?將XML視圖項與用戶輸入的URL和文本在綁定??
  • ????????????textView.setText(imageAndText.getText());//加載TEXT??
  • ????????????ImageView?iv?=?(ImageView)?convertView.findViewById(R.id.sItemIcon);??
  • ????????????iv.setBackgroundResource(R.drawable.rc_item_bg);??
  • ??????????????
  • ????????????//?加載IMG,并設定到ImageView中??
  • ????????????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();??????
  • ????????????????????????//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)?{??
  • ????????????????//?TODO?Auto-generated?method?stub??
  • ??????????????????
  • ????????????}??
  • ????????};??
  • ??
  • ??
  • }??
  • 這里的代碼較上篇增加了一個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)?{??
  • ????????????????????????????//?TODO?Auto-generated?catch?block??
  • ????????????????????????????e.printStackTrace();??
  • ????????????????????????}??
  • ????????????????????}??
  • ????????????????}??
  • ????????????????//?如果是第一次加載XML就加載圖片,對于是不是在顯示范圍內的加載控制放在VIEW中??
  • ????????????????if?(mAllowLoad?&&?firstLoad)?{??
  • ????????????????????LoadImg(pos,?imageUrl,?imageCallback);??
  • ????????????????}??
  • ????????????????//?對于在顯示范圍內的,對其加載IMG??
  • ????????????????if?(mAllowLoad?&&?pos?<=?mStopLoadLimit??
  • ????????????????????????&&?pos?>=?mStartLoadLimit)?{??
  • ????????????????????LoadImg(pos,?imageUrl,?imageCallback);??
  • ????????????????}??
  • ??
  • ????????????}??
  • ????????}.start();??
  • ????????return?null;??
  • ????}//?loadDrawable---end??
  • ??
  • ????public?void?LoadImg(final?Integer?pos,?final?String?imageUrl,??
  • ????????????final?ImageCallback?imageCallback)?{??
  • ????????//?首先判斷是否在緩存中??
  • ????????//?但有個問題是:ImageCache可能會越來越大,以至用戶內存用光,所以要用SoftReference(弱引用)來實現??
  • ????????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;??
  • ????????????}??
  • ????????}??
  • ????????//?嘗試從URL中加載??
  • ????????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();??
  • ????????}??
  • ??
  • ????}??
  • ??
  • ????//?根據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?imageLoaded(Drawable?imageDrawable,final?ImageView??
  • ????????//?imageView);??
  • ????????//?public?void?onError(final?ImageView?imageView);??
  • ????????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)?{??
  • ????????????????????????//?TODO?Auto-generated?catch?block??
  • ????????????????????????e.printStackTrace();??
  • ????????????????????}??
  • ????????????????}??
  • ????????????}??
  • ????????????//?如果是第一次加載XML就加載圖片,對于是不是在顯示范圍內的加載控制放在VIEW中??
  • ????????????if?(mAllowLoad?&&?firstLoad)?{??
  • ????????????????LoadImg(pos,?imageUrl,?imageCallback);??
  • ????????????}??
  • ????????????//?對于在顯示范圍內的,對其加載IMG??
  • ????????????if?(mAllowLoad?&&?pos?<=?mStopLoadLimit??
  • ????????????????????&&?pos?>=?mStartLoadLimit)?{??
  • ????????????????LoadImg(pos,?imageUrl,?imageCallback);??
  • ????????????}??
  • ??
  • ????????}??
  • ????}.start();??
  • ????return?null;??
  • }//?loadDrawable---end??
  • 這里較上回的不同點在于加了鎖---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 ? ,謝謝!!!!!!

    總結

    以上是生活随笔為你收集整理的异步加载图片(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。