码迷,mamicode.com
首页 > 系统相关 > 详细

ListView异步加载 LruCache缓存 滑动状态监听

时间:2016-05-12 12:45:17      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:

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<String, Bitmap> mCaches;
    private ListView mListView;
    private Set<NewsIconAsyncTask> mTask;

    public ImageLoader(ListView mListView) {
        this.mListView = mListView;
        mTask = new HashSet<>();
        //获取最大可用内存
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        //设置换成大小值
        int cacheSize = maxMemory / 4;
        mCaches = new LruCache<String, Bitmap>(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<String, Void, Bitmap> {
        //        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<NewsBean> mList;
    private LayoutInflater mLayoutInflater;
    private ImageLoader mImageLoader;
    private int mStart, mEnd;
    public static String[] URLS;
    private boolean mFirstIn;

    public NewsAdapter(Context context, List<NewsBean> 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;
    }
}

ListView异步加载 LruCache缓存 滑动状态监听

标签:

原文地址:http://blog.csdn.net/fang323619/article/details/51364294

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!