Android ListView与RecyclerView

来源:互联网 发布:部落冲突防御设施数据 编辑:程序博客网 时间:2024/05/18 18:17

Android中,最复杂的原生控件就是ListView,在support-v7中,Google提供了一种功能更加丰富的控件来代替ListView,那就是RecyclerView,本篇文章,就来解析一下ListView与RecyclerView。

使用ListView控件需要为设置一个Adapter:

public class listadapter extends BaseAdapter {    private Context context;    private List<listitem> list;    class ViewHolder {        ImageView imageView;        TextView textView;    }    public listadapter(Context context, List<listitem> list) {        this.context = context;        this.list = list;    }    public listitem getItem(int position) {        return list.get(position);    }    public long getItemId(int postion) {        return postion;    }    public int getCount() {        return list.size();    }    public View getView(int position, View convertview, ViewGroup parent) {        listitem listitem = getItem(position);                View view;        ViewHolder viewHolder;        if(convertview == null) {            int id = getItemViewType(position);            viewHolder = new ViewHolder();            if(id == 0) {                view = LayoutInflater.from(context).inflate(R.layout.listitem_layout0, parent, false);                viewHolder.imageView = (ImageView) view.findViewById(R.id.image0);                viewHolder.textView = (TextView) view.findViewById(R.id.name0);                view.setTag(viewHolder);            } else {                view = LayoutInflater.from(context).inflate(R.layout.listitem_layout1, parent, false);                viewHolder.imageView = (ImageView) view.findViewById(R.id.image1);                viewHolder.textView = (TextView) view.findViewById(R.id.name1);                view.setTag(viewHolder);            }        } else {            view = convertview;            viewHolder = (ViewHolder) view.getTag();        }        viewHolder.imageView.setImageResource(listitem.getImageId());        viewHolder.textView.setText(listitem.getName());        return view;    }    @Override    public int getItemViewType(int position) {        if(position < 6) return 0;        else return 1;    }    @Override    public int getViewTypeCount() {        return 2;    }}

上面的代码中,Adapter继承自BaseAdapter, 复写了六种方法。其中

public listitem getItem(int position) {    return list.get(position);}public long getItemId(int postion) {    return postion;}public int getCount() {    return list.size();}public View getView(int position, View convertview, ViewGroup parent) {

}


四种方法最为基本(注意getItemId方法的返回值类型为long),getView在每次获取View时都会被调用,里面复写的逻辑尽可能简单。

此外,使用convertview与ViewHolder来对ListView进行优化。

@Overridepublic int getItemViewType(int position) {    if(position < 6) return 0;    else return 1;}@Overridepublic int getViewTypeCount() {    return 2;}
复写以上两种方法,可以实现ListView的多种布局。getViewTypeCount方法返回布局类型的数目,getItemViewType方法返回布局类型的序号,范围为0~n-1(n为布局类型的数目)。


ListView还可以直接与Android自带的轻量级数据库sqlite相关联。


相比于ListView,RecyclerView除了需要设置Adapter,还需要设置LayoutManager。

class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder>{    private Set<BitmapWorkerTask> taskCollection;    //private List<square> squareList = new ArrayList<>();    private LruCache<String, Bitmap> bitmapLruCache;    private RecyclerView recyclerView;    private StaggeredGridLayoutManager layoutManager;    private int firstVisibleItem, lastVisibleItem;    private boolean isFirstEnter = true;    @Override    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)    {        MyViewHolder holder = new MyViewHolder(LayoutInflater.from(                parent.getContext()).inflate(R.layout.squareitem, parent,                false));        return holder;    }    @Override    public void onBindViewHolder(MyViewHolder holder, int position)    {        final String url = image.imageThumbUrls[position];        ImageView bg = holder.bg;        bg.setTag(url);        Bitmap bitmap = getBitmapFromMemoryCache(url);        if (bitmap != null) {            bg.setImageBitmap(bitmap);        } else {            bg.setImageResource(R.color.black_overlay);        }    }    @Override    public int getItemCount()    {        return image.imageThumbUrls.length;    }    class MyViewHolder extends RecyclerView.ViewHolder    {        ImageView bg;        public MyViewHolder(View view)        {            super(view);            bg = (ImageView) view.findViewById(R.id.bgimage);        }    }    public RecyclerViewAdapter(RecyclerView recyclerView) {        //this.squareList = squareList;        this.recyclerView = recyclerView;        layoutManager = (StaggeredGridLayoutManager)recyclerView.getLayoutManager();        taskCollection = new HashSet<>();        int maxMemory = (int) Runtime.getRuntime().maxMemory();        int cacheSize = maxMemory / 8;        bitmapLruCache = new LruCache<String, Bitmap>(cacheSize) {            @Override            protected int sizeOf(String key,  Bitmap bitmap) {                return bitmap.getByteCount();            }        };        System.out.println("CacheSize : " + cacheSize);        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {            @Override            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {                super.onScrollStateChanged(recyclerView, newState);                if (newState == SCROLL_STATE_IDLE) {                    loadBitmaps(firstVisibleItem, lastVisibleItem);                } else {                    cancelAllTasks();                }            }            @Override            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {                super.onScrolled(recyclerView, dx, dy);                firstVisibleItem =  layoutManager.findFirstVisibleItemPositions(null)[0];                lastVisibleItem = layoutManager.findLastVisibleItemPositions(null)[1];                System.out.println("firstvisibleitem : " + firstVisibleItem);                System.out.println("lastvisibleitem : " + lastVisibleItem);                if (isFirstEnter && lastVisibleItem - firstVisibleItem > 0) {                    loadBitmaps(firstVisibleItem, lastVisibleItem);                    isFirstEnter = false;                }            }        });    }    private void loadBitmaps(int firstVisibleItem, int lastVisibleItem) {        try {            for (int i = firstVisibleItem; i <= lastVisibleItem; i ++) {                String imageUrl = image.imageThumbUrls[i];                Bitmap bitmap = getBitmapFromMemoryCache(imageUrl);                if (bitmap == null) {                    BitmapWorkerTask task = new BitmapWorkerTask();                    taskCollection.add(task);                    task.execute(imageUrl);                    System.out.println("task is executing");                } else {                    ImageView imageView = (ImageView) recyclerView.findViewWithTag(imageUrl);                    if (imageView != null && bitmap != null) {                        imageView.setImageBitmap(bitmap);                    }                }            }        } catch (Exception e) {            e.printStackTrace();            System.out.println("task failed");        }    }    public void addBitmapToMemoryCache(String key, Bitmap bitmap) {        if (getBitmapFromMemoryCache(key) == null) {            bitmapLruCache.put(key, bitmap);        }    }    public Bitmap getBitmapFromMemoryCache(String key) {        return bitmapLruCache.get(key);    }    public void cancelAllTasks() {        if (taskCollection != null) {            for (BitmapWorkerTask task : taskCollection) {                task.cancel(false);            }        }    }    class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {        private String imageUrl;        @Override        protected Bitmap doInBackground(String... params) {            imageUrl = params[0];            Bitmap bitmap = downloadBitmap(params[0]);            if (bitmap != null) {                addBitmapToMemoryCache(params[0], bitmap);            }            return bitmap;        }        @Override        protected void onPostExecute(Bitmap bitmap) {            super.onPostExecute(bitmap);            ImageView imageView  = (ImageView) recyclerView.findViewWithTag(imageUrl);            if(imageView != null && bitmap != null) {                imageView.setImageBitmap(bitmap);            }            taskCollection.remove(this);        }        private Bitmap downloadBitmap(String imageUrl) {            Bitmap bitmap = null;            HttpURLConnection con = null;            try {                URL url = new URL(imageUrl);                con = (HttpURLConnection) url.openConnection();                con.setConnectTimeout(5000);                con.setReadTimeout(10000);                bitmap = BitmapFactory.decodeStream(con.getInputStream());            } catch (Exception e) {                e.printStackTrace();;            } finally {                if (con != null) {                    con.disconnect();                }            }            return bitmap;        }    }}
上面的代码中使用了LRUCache对图片进行缓存,同时对RecyclerView进行了滑动监听,仅在静止时加载图片。

RecyclerView使用的Adapter继承了RecyclerView.Adapter<T>,泛型T为RecyclerView.ViewHolder类型,需要在Adapter中自己设置,继承RecyclerView.ViewHolder,重写构造函数。其他需要重写的三个函数:

@Overridepublic MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)@Overridepublic void onBindViewHolder(MyViewHolder holder, int position)@Overridepublic int getItemCount()onCreateViewHolder方法返回ViewHolder。在onBindViewHolder方法中设置Item的View,相当于ListView中的getView方法,不过onBinderViewHolder无需返回View。getItemCount方法返回Item的数量,相当于ListView中的getCount方法。LayoutManager表示RecyclerView的布局格式。不同于ListView的线性的颇显单调的布局,RecyclerView提供了LinearLayourManager(线性布局),GridLayoutManager(方格布局)和StaggeredGridLayoutManager(瀑布流布局)三种布局格式。一次性解决了ListView和GridView,还提供了瀑布流的布局格式。此外,还可以同过setItemAnimatoraddItemDecoration方法来设置RecyclerView的增删Item的动画以及分割线的格式。这两个属性,我们下回再说。

0 0
原创粉丝点击