激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Android - Android ListView異步加載圖片方法詳解

Android ListView異步加載圖片方法詳解

2021-06-19 17:37炫_愛羊 Android

這篇文章主要介紹了Android ListView異步加載圖片方法,結合實例形式較為詳細的分析了ListView異步加載圖片的原理與相關實現技巧,需要的朋友可以參考下

本文實例講述了android listview異步加載圖片方法。分享給大家供大家參考,具體如下:

先說說這篇文章的優點把,開啟線程異步加載圖片,然后刷新ui顯示圖片,而且通過弱引用緩存網絡加載的圖片,節省了再次連接網絡的開銷。

這樣做無疑是非常可取的方法,但是加載圖片時仍然會感覺到輕微的卡屏現象,特別是listview里的item在進行快速滑動的時候。

我找了一下原因,可能是在listview快速滑動屏幕的時候劃過的item太多 而且每次調用getview方法后就會異步的在過去某個時間內用handler刷新一下ui,

如果在同一時間調用handler刷新ui次數多了就會造成這樣的卡屏現象。

后來又一想,其實我們完全沒有必要在listview正在滑動的時候去后臺加載圖片(不管這是圖片是在緩存里還是在網絡上),這樣無疑造成了很大的資源浪費。

我們只需要在listview滑動停止之后再去加載listview里面顯示的幾個item里面的圖片就好了。

根據以上想法,我做了一些設計改造:

1.在adapter 的 getview方法里面啟動加載圖片的thread,如果listview在滑動則wait

2.監聽listview滑動停止事件,獲得listview顯示的item的最上面和最下面的序號,并喚醒所有加載圖片的thread,判斷加載圖片的序號是否是在范圍內,如果是則繼續加載,如果不是則結束thread

部分代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
@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
  }
};
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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;
    }
  }
}

除了本身已有的弱引用緩存圖片,我還添加了本地sd卡緩存圖片(這兩種緩存方法各有好處,如果圖片經常變化建議內存緩存圖片,如果是不經常修改的圖片建議sd卡緩存)

希望本文所述對大家android程序設計有所幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产精品啪一品二区三区粉嫩 | 一本色道久久综合狠狠躁篇适合什么人看 | 久久久久免费精品国产小说色大师 | 蜜桃视频在线观看视频 | 黄片一级毛片 | 久久免费激情视频 | 黄色网络免费看 | 网站激情 | xxxx hd videos| 91 久久| 日韩精品久久久久久 | 超污视频在线看 | 中国妞xxxhd露脸偷拍视频 | 国产日本欧美在线观看 | 亚洲一区成人 | 蜜桃欧美性大片免费视频 | 国产在线午夜 | 久久精品网站视频 | 国产成人强伦免费视频网站 | 久久国产精品99国产 | 久久99久久98精品免观看软件 | 伊人一二三四区 | 色吧综合网| 精品国产一区二区三区四区在线 | 亚洲午夜不卡 | ,欧美特黄特色三级视频在线观看 | 最新毛片在线观看 | 欧美a∨一区二区三区久久黄 | 羞羞电影在线观看www | 黑人日比 | 中国产一级毛片 | 一日本道久久久精品国产 | 亚洲视频成人在线 | 欧美精品一区二区久久 | 欧美一级视频网站 | 日韩视频区 | 欧美人的天堂一区二区三区 | 午夜男人在线观看 | 欧美日韩在线影院 | chengrenzaixian | 91久久99热青草国产 |