Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> ListView異步加載 LruCache緩存 滑動狀態監聽

ListView異步加載 LruCache緩存 滑動狀態監聽

編輯:關於Android編程

Android異步加載的總結。除了LruCache,我們還可以使用DiskLruCache這個第三方的類來實現“二級緩存”。異步加載不僅僅是獲取網絡資源,我們可以加所有耗時的操作都看成異步加載,所有通過耗時的操作獲取的結果我們都可以通過緩存來提高效率,比如我們可以利用這裡的LruCache和DiskLruCache(這個緩存一般是用於緩存從網絡獲取的圖片,視頻等大的資源,這個時候我們一般和LruCache結合使用),使用Cache有個缺點,就是我們不能保證我們的數據是實時的,所以在realtime需求高的應用中,我們不應該使用緩存。而對於本地資源,我們很少用緩存的,就算是操作SQLite數據庫,我們也很少會用到LruCache,但是也有使用的。

listview的優化
1. 復用convertView,減少item view 的加載次數
2.使用holder,減少獲取item中子控件的次數
3.使用異步加載,防止阻塞主線程
4.使用google提供的LruCache類,將圖片緩存到內存中,減少從網絡獲取圖片的次數
加快速度,節省流量。lru 算法
5. 防止圖面緩存引起的錯位問題,給每個imageView添加一個tag,用URL做標識,加載圖片時
只有當前的URL和要加載圖片的imageView的tag中的URL相同時,才加載.
6.監聽listView的滾動狀態。滾動時停止記載,記錄當前可見item的起始和結束位置,並記錄他們的url,滾動結束後載再加載。 防止滑動中加載數據造成卡頓,和不必要的流量浪費.

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.util.LruCache;
import android.widget.ImageView;
import android.widget.ListView;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;

/**
 * Created by Aldrich_jia on 2016-5-9.
 */
public class ImageLoader {
    private ImageView mImageView;
    private String iconUrl;
    //創建cache
    private LruCache mCaches;
    private ListView mListView;
    private Set mTask;

    public ImageLoader(ListView mListView) {
        this.mListView = mListView;
        mTask = new HashSet<>();
        //獲取最大可用內存
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        //設置換成大小值
        int cacheSize = maxMemory / 4;
        mCaches = new LruCache(cacheSize) {
            //告訴系統,每次存入緩存多大
            @Override
            protected int sizeOf(String key, Bitmap value) {
                //每次存入緩存時調用
                return value.getByteCount();
            }
        };
    }

    //從緩存中獲取數據
    public Bitmap getBitmapfromCache(String url) {
        return mCaches.get(url);
    }

    //增加到緩存
    private void addBitmaptoCache(String url, Bitmap bitmap) {
        if (getBitmapfromCache(url) == null) {
            mCaches.put(url, bitmap);
        }
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (mImageView.getTag().equals(iconUrl)) {
                mImageView.setImageBitmap((Bitmap) msg.obj);
            }
        }
    };

    public void showImageByThread(ImageView imageView, final String urlString) {
        this.mImageView = imageView;
        this.iconUrl = urlString;
        new Thread(new Runnable() {
            @Override
            public void run() {
                Bitmap mbitamp = getBitmapForURL(urlString);
                Message message = Message.obtain();
                message.obj = mbitamp;
                mHandler.sendMessage(message);
            }
        }).start();
    }

    private Bitmap getBitmapForURL(String urlString) {
        Bitmap mbitmap;
        InputStream is = null;
        try {
            URL url = new URL(urlString);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            is = new BufferedInputStream(urlConnection.getInputStream());
            mbitmap = BitmapFactory.decodeStream(is);
            urlConnection.disconnect();
            return mbitmap;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public void showImageByAsync(ImageView imageView, String mUrl) {
        //從緩存中取出對應的圖片
        Bitmap bitmap = getBitmapfromCache(mUrl);
        //如果緩存中沒有,必須去下載
        if (bitmap == null) {
            imageView.setImageResource(R.mipmap.ic_launcher);
//            new NewsIconAsyncTask(imageView, mUrl).execute(mUrl);
        } else {
            imageView.setImageBitmap(bitmap);
        }
    }

    /**
     * 顯示從start到end中的圖片
     *
     * @param start
     * @param end
     */
    public void loadImages(int start, int end) {
        for (int i = start; i < end; i++) {
            String url = NewsAdapter.URLS[i];
            //從緩存中取出對應的圖片
            Bitmap bitmap = getBitmapfromCache(url);
            //如果緩存中沒有,必須去下載
            if (bitmap == null) {
                NewsIconAsyncTask asyncTask = new NewsIconAsyncTask(url);
                asyncTask.execute(url);
                mTask.add(asyncTask);
            } else {
                ImageView imageView = (ImageView) mListView.findViewWithTag(url);
                imageView.setImageBitmap(bitmap);
            }
        }
    }

    public void cancelAllTask() {
        if (mTask != null) {
            for (NewsIconAsyncTask task : mTask) {
                task.cancel(false);
            }
        }
    }

    private class NewsIconAsyncTask extends AsyncTask {
        //        private ImageView mImageView;
        private String mUrl;

        public NewsIconAsyncTask(String mUrl) {
//            this.mImageView = mImageView;
            this.mUrl = mUrl;
        }

        @Override
        protected Bitmap doInBackground(String... strings) {
            String url = strings[0];
            //從網絡上獲取圖片
            Bitmap bitmap = getBitmapForURL(url);
            if (bitmap != null) {
                //將不在緩存的圖片加入緩存
                addBitmaptoCache(url, bitmap);
            }
            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            ImageView imageView = (ImageView) mListView.findViewWithTag(mUrl);
            if (imageView != null && bitmap != null) {
                imageView.setImageBitmap(bitmap);
            }
            mTask.remove(this);
//            if (mImageView.getTag().equals(mUrl)) {
//                mImageView.setImageBitmap(bitmap);
//
//            }
        }
    }
}
import android.content.Context;
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;

import java.util.List;

/**
 * Created by Aldrich_jia on 2016-5-9.
 */
public class NewsAdapter extends BaseAdapter implements AbsListView.OnScrollListener {
    private List mList;
    private LayoutInflater mLayoutInflater;
    private ImageLoader mImageLoader;
    private int mStart, mEnd;
    public static String[] URLS;
    private boolean mFirstIn;

    public NewsAdapter(Context context, List mList, ListView listView) {
        mLayoutInflater = LayoutInflater.from(context);
        this.mList = mList;
        mImageLoader = new ImageLoader(listView);
        URLS = new String[mList.size()];
        for (int i = 0; i < mList.size(); i++) {
            URLS[i] = mList.get(i).newsIconUrl;
        }

        listView.setOnScrollListener(this);
        mFirstIn = true;
    }

    @Override
    public int getCount() {
        return mList.size();
    }

    @Override
    public Object getItem(int i) {
        return mList.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHoloder viewHoloder = null;
        if (view == null) {
            viewHoloder = new ViewHoloder();
            view = mLayoutInflater.inflate(R.layout.item_layout, null);
            viewHoloder.ivIcon = (ImageView) view.findViewById(R.id.iv_icon);
            viewHoloder.tvTitle = (TextView) view.findViewById(R.id.tv_title);
            viewHoloder.tvContent = (TextView) view.findViewById(R.id.tv_content);
            view.setTag(viewHoloder);
        } else {
            viewHoloder = (ViewHoloder) view.getTag();
        }
        String iconUrl = mList.get(i).newsIconUrl;
        viewHoloder.ivIcon.setTag(iconUrl);
        viewHoloder.ivIcon.setImageResource(R.mipmap.ic_launcher);
//        new ImageLoader().showImageByThread(viewHoloder.ivIcon,iconUrl);
        mImageLoader.showImageByAsync(viewHoloder.ivIcon, iconUrl);
        viewHoloder.tvTitle.setText(mList.get(i).newsTitle);
        viewHoloder.tvContent.setText(mList.get(i).newsContent);


        return view;
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (scrollState == SCROLL_STATE_IDLE) {
            //加載可見項
            mImageLoader.loadImages(mStart, mEnd);
        } else {
            //停止任務
            mImageLoader.cancelAllTask();
        }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        mStart = firstVisibleItem;
        mEnd = firstVisibleItem + visibleItemCount;
        //第一次顯示的時候調用
        if (mFirstIn && visibleItemCount > 0) {
            mImageLoader.loadImages(mStart, mEnd);
            mFirstIn = false;
        }
    }


    class ViewHoloder {
        private TextView tvTitle, tvContent;
        private ImageView ivIcon;
    }
}
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved