解決ListView滑動是卡的問題解決,實現異步加載圖片解決
ListView是最為常見的空間之一,現在的應用的呈現形式大多數都需要用到ListView來呈現,以列表的方式最直觀最便于操作。
那么在使用的過程中大家一定使用adapter適配器來匹配這個ListView,問題就來了,如果直接使用sampleAdapter的話,會出 現諸多的問題,諸如滾動的時候很卡,特別是每一行都有頭像啊什么的,再加上數據量一大,兼職就卡的不行,那么先來說說解決卡的問題的簡單的實現方法吧。
首先需要自己來寫一個myAdapter繼承與BaseAdapter。
然后最關鍵的是在getView方法中做到以下幾點判斷convertView是否為空,這樣可以避免每次滾動都去新建,可以節約大量資源,同時對 于圖片采用開啟線程以異步加載的方式來加載它,又可以節約一部分資源,同時,將加載下來的圖片緩存到本地,當下一次的時候首先讀取本地圖片,第一可以節約 流量,其次速度非常快(不過服務器圖片更新了這個要想好解決方案,不然你本地的圖片不會被替換掉)。最后就是在滾動時間的時候讓異步加載暫停,等手放開的 時候再加載,這樣可以保證滾動的超級流暢,不過同時會出現滾動比較大的時候圖片都還是空的沒有加載的現象,反正自己斟酌優劣吧,代碼都有哈!接下來上代碼 了
首先是主activity
package com.challen; import java.util.Vector; import cindy.android.test.synclistview.R; import android.app.Activity; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; public class TestListViewActivity extends Activity implements AdapterView.OnItemClickListener { ListView viewBookList; BookItemAdapter adapter; @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); 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); } }).start(); } public void loadDate() { for (int i = 0; i < 100; i++) { adapter.addBook("我是challen的測試異步加" + i, "1", "http://ww1.sinaimg.cn/thumbnail/80ab1ad3gw1dx8tfjvbgdj.jpg"); adapter.addBook("小美" + i, "2", "http://ww2.sinaimg.cn/thumbnail/7f9fd9a9jw1dtyrqrh4mjj.jpg"); adapter.addBook("金總" + i, "3", "http://ww3.sinaimg.cn/thumbnail/9d57e8e4jw1dx6topumz5j.jpg"); adapter.addBook("創意鋪子" + i, "4", "http://www.pfwx.com/files/article/image/3/3237/3237s.jpg"); adapter.addBook("人名日報" + i, "5", "http://ww2.sinaimg.cn/thumbnail/9263d293jw1dx8snx58s7j.jpg"); adapter.addBook("名字是亂明的" + i, "6", "http://tp1.sinaimg.cn/1660452532/50/5646449168/0"); adapter.addBook("帥哥即將出現" + i, "7", "http://p1.qhimg.com/t01a869bb64c7f3d8c6.png"); adapter.addBook("注意了哦" + i, "8", "http://www.baidu.com/img/baidu_jgylogo3.gif"); adapter.addBook("來拉" + i, "9", "http://tp4.sinaimg.cn/2190322767/50/5605436918/1"); adapter.addBook("這個就是我啦" + i, "10", "http://avatar.csdn.net/E/7/2/3_jkingcl.jpg"); } } private static final int REFRESH_LIST = 0x10001; public static final int SHOW_STR_TOAST = 0; public static final int SHOW_RES_TOAST = 1; private Handler pichandler = new Handler() { @Override public void handleMessage(Message msg) { if (!Thread.currentThread().isInterrupted()) { handleOtherMessage(msg.what); } } }; public void sendMessage(int flag) { pichandler.sendEmptyMessage(flag); } protected void handleOtherMessage(int flag) { switch (flag) { case REFRESH_LIST: adapter.notifyDataSetChanged(); default: break; } } @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // TODO Auto-generated method stub } public class BookItemAdapter extends BaseAdapter { 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; } private LayoutInflater mInflater; 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(); mListView = listView; /* * * 這一句話取消掉注釋的話,那么能更加的節省資源,不過體驗稍微有點, * 你滑動的時候不會讀取圖片,當手放開后才開始度圖片速度更快,你們可以試一試 * */ // mListView.setOnScrollListener(onScrollListener); } public void addBook(String book_name, String author, String out_book_pic) { BookModel model = new BookModel(); model.book_name = book_name; model.author = author; 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.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, model.author); 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: syncImageLoader.lock(); break; case AbsListView.OnScrollListener.SCROLL_STATE_IDLE: 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 } }; } }其次是實現異步加載和緩存圖片的功能代碼loader.java
package com.challen; 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,String author1) { final OnImageLoadListener mListener = listener; final String mImageUrl = imageUrl; final Integer mt = t; final String author = author1; new Thread(new Runnable() { @Override public void run() { if(!mAllowLoad){ synchronized (lock) { try { lock.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } if(mAllowLoad && firstLoad){ loadImage(mImageUrl, mt, mListener,author); } if(mAllowLoad && mt <= mStopLoadLimit && mt >= mStartLoadLimit){ loadImage(mImageUrl, mt, mListener,author); } } }).start(); } private void loadImage(final String mImageUrl,final Integer mt,final OnImageLoadListener mListener,final String author){ if (imageCache.containsKey(mImageUrl)) { System.out.println("drawable"); 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,author); 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,String author) throws IOException { //是否SD卡可用 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ //檢查是或有保存圖片的文件夾,沒有就穿件一個 String FileUrl = Environment.getExternalStorageDirectory()+"/TestSyncListView/"; File folder = new File(FileUrl); if(!folder.exists()){ folder.mkdir(); } File f = new File(FileUrl+author+".jpg"); //SD卡中是否有該文件,有則直接讀取返回 if(f.exists()){ FileInputStream fis = new FileInputStream(f); Drawable d = Drawable.createFromStream(fis, "src"); return d; } //沒有的話則去連接下載,并寫入到SD卡中 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,author); } //SD卡不可用則直接加載使用 else{ URL m = new URL(url); InputStream i = (InputStream) m.getContent(); Drawable d = Drawable.createFromStream(i, "src"); return d; } } }
本文由用戶 homepp 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!