Android中ListView的使用及优化

一.ListView常规使用

1.list item布局文件



    
    

2.Adapter
public class MyAdapter extends BaseAdapter {
    private List mData;
    private LayoutInflater mInflater;

    public MyAdapter(Context context, List mData) {
        this.mData = mData;
        mInflater = LayoutInflater.from(context);
    }

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

    @Override
    public Object getItem(int position) {
        return mData.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder = new ViewHolder();
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.list_item, null);
            viewHolder.imageView = (ImageView) convertView.findViewById(R.id.listview_image);
            viewHolder.textView = (TextView)convertView.findViewById(R.id.listview_text);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        viewHolder.imageView.setImageResource(R.mipmap.ic_launcher);
        viewHolder.textView.setText(mData.get(position).toString());
        return convertView;
    }

    private final class ViewHolder {
        ImageView imageView;
        TextView textView;
    }
}
3.Activity
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);

        for(int i = 0; i < 20; i++) {
            list.add(Integer.valueOf(i));
        }

        listView = (ListView) findViewById(R.id.list_view);
        myAdapter = new MyAdapter(this, list);
        listView.setAdapter(myAdapter);
    }
4.Layout


    

5.效果图:


优化方式:

1.重用convertView:通过重用convertView来减少不必要的view的创建,另外Inflate操作会把xml文件实例化成相应的View实例,是耗时操作。复用convertView的时候,当图片加载采用异步的方式加载的时候可能出现错位的情况,解决办法是给给 ImageView 设置一个 tag, 并预设一个图片。点击打开链接

实际上跟多图片加载框架比如Glide加载图片都是异步的,提高性能。


2.减少findViewById()操作:将xml文件中的元素封装成viewHolder静态类,通过convertView的setTag和getTag将view和相应的对象绑定在一起,避免不必要的findViewById操作。

3.避免在getView方法中作耗时操作:例如加载本地Image需要载入内存以及解析Bitmap,都是比较耗时的操作,如果用户快速滑动listView,会因为getView逻辑过于复杂而造成滑动卡顿的现象。用户滑动的时候不要加载图片,待滑动完成再加载,可以使用第三方的库glide。

4.Item的布局层次结构尽量简单,避免布局太深或者不必要的重绘。

5.尽量保证Adapter的hasStablelds()返回true,这样在notifyDataSetChaged()的时候,如果Item内容没有变化,listView将不会重绘这个View,达到优化的目的。

6.在一些场景中,ScrollView内会包含多个ListView,可以把listView的高度写死固定下来。由于ScrollView在快速下滑过程中需要大量计算每个listView的高度,阻塞UI线程导致卡顿现象,如果每一个item的高度是均匀的,可以通过计算把listView的高度确定下来。

7.使用RecyclerView代替ListView:RecyclerView的用法

每个item内容的变动,ListView都需要调用notifyDataSetChanged来更新全部item。Recycler可以实现当前item的局部刷新,并且引入了增加和移除的动态效果,在性能和定制上有很大改善。

8.开启硬件加速。


二.ListView的扩展

1.设置列别分隔线

android:divider="@color/colorPrimary"
android:dividerHeight="10dp"

2.隐藏滚动条
android:scrollbars="none"
3.改变item点击效果
android:listSelector="@android:color/transparent"
4.设置ListView需要显示在第几项
listView.setSelection(N);
或者
listView.smoothScrollToPosition(N);
5.动态改变ListView
mData.add("string");
mAdapter.notifyDataSetChanded();
6.遍历ListView
        for (int i = 0; i < listView.getCount(); i++) {
            View view = listView.getChildAt(i);
        }
7.ListView滑动监听

OnTouchListener

        listView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        //
                        break;
                    case MotionEvent.ACTION_HOVER_MOVE:
                        //
                        break;
                    case MotionEvent.ACTION_UP:
                        //
                        break;
                }
                return false;
            }
        });

OnScrollListener

        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                switch (scrollState) {
                    case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
                        //
                        break;
                    case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
                        //
                        break;
                    case  AbsListView.OnScrollListener.SCROLL_STATE_FLING:
                        //
                        break;
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0) {
                    //滚动到最后一行
                }

                int lastVisibleItemPosition = 0;
                if (firstVisibleItem > lastVisibleItemPosition) {
                    //上滑
                } else if (firstVisibleItem < lastVisibleItemPosition) {
                    //下滑
                }
                lastVisibleItemPosition = firstVisibleItem;

            }
        });
//获取可见区域最后一个可见item id

listView.getLastVisiblePosition();

//获取可见区域第一个可见item id

listView.getFirstVisiblePosition();
8.具有弹性的ListView

重写LisyView的overScrollBy()方法

    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
        return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, initHeight(100), isTouchEvent);
    }

    private int initHeight(int height) {
        float density = mContext.getResources().getDisplayMetrics().density;
        return (int) (height * density);
    }
9.设置不同的item,Adapter中的type方法

    @Override
    public int getViewTypeCount() {
        return super.getViewTypeCount();
    }

你可能感兴趣的:(Android)