ListView使用和优化措施

1. 基本使用

直接代码:

list_view_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:src="@mipmap/ic_launcher"/>

    <TextView
        android:id="@+id/text"
        android:layout_margin="10dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="1"
        android:textSize="20sp"/>

</LinearLayout>

activity_list_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.shuidi.listviewtest.ListViewActivity">

    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </ListView>

</LinearLayout>

ListViewActivity.java

public class ListViewActivity extends AppCompatActivity {

    ListView mListView;
    ListAdapter mAdatper;
    List<String> list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list_view);
        mListView = (ListView) findViewById(R.id.listview);
        list = getListData();
        mAdatper = new ListViewAdapter(this,list);
        mListView.setAdapter(mAdatper);
    }

    private List<String> getListData(){
        List<String> list = new ArrayList<>();
        list.add("One");
        list.add("Two");
        list.add("Three");
        list.add("Four");
        list.add("Five");
        list.add("Six");
        list.add("Seven");
        list.add("Eight");
        return list;
    }

    private class ListViewAdapter extends BaseAdapter {

        LayoutInflater inflater;
        List<String> list;


        public ListViewAdapter(Context context,List<String> stringList){
            inflater = LayoutInflater.from(context);
            list = stringList;
        }

        @Override
        public Object getItem(int i) {
            return null;
        }

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

        @Override
        public int getCount() {
            return list==null? 0:list.size();
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            View view;
            if (convertView==null) {
                view = inflater.inflate(R.layout.list_view_item,null);
                TextView textView = (TextView)view.findViewById(R.id.text);
                viewHolder = new ViewHolder();
                viewHolder.tx = textView;
                view.setTag(textView);
            } else {
                view = convertView;
                viewHolder = (ViewHolder)view.getTag();
            }
            viewHolder.tx.setText(list.get(position));
            return view;
        }
    }

    private static class ViewHolder{
        public TextView tx;
    }

}

2. 优化措施

2.1 复用ConvertView
2.2 使用View Holder模式
2.3 分批加载与分页加载相结合

我们需要进行分批加载,比如说1000条新闻的List集合,我们一次加载20条,等到用户翻页到底部的时候,我们再添加下面的20条到List中,再使用Adapter刷新ListView,这样用户一次只需要等待20条数据的传输时间,不需要一次等待好几分钟把数据都加载完再在ListView上显示。其次这样也可以缓解很多条新闻一次加载进行产生OOM应用崩溃的情况。

实际上,分批加载也不能完全解决问题,因为虽然我们在分批中一次只增加20条数据到List集合中,然后再刷新到ListView中去,假如有10万条数据,如果我们顺利读到最后这个List集合中还是会累积海量条数的数据,还是可能会造成OOM的情况,这时候我们就需要用到分页,比如说我们将这10万条数据分为1000页,每一页100条数据,每一页加载时都覆盖掉上一页中List集合中的内容,然后每一页内再使用分批加载,这样用户的体验就会相对好一些。

文章 已经说明了如何进行分批加载, 可以在这个基础之上再实现分页加载.

2.4 将ListView的scrollingCache和animateCache属性设置为false(默认是true)

3. 设计模式

3.1. Adapter模式

ListView充当Client角色,接口Adapter充当Target,BaseAdapter充当Adapter,而ListView的数据对象就是Adaptee。
Adapter接口抽象出ListView需要的接口getItem,getCount,getView。
BaseAdapter子类中实现的Adapter接口,其实是对数据对象的操作,也就是对Adaptee依赖关系。

3.2. Observer模式

当ListView的数据发生变化时,调用Adapter的notifyDataSetChanged函数,这个函数又会调用DataSetObservable的notifyChanged函数,这个函数会调用所有观察者 (AdapterDataSetObserver) 的onChanged方法。这就是一个观察者模式!

最后我们再捋一捋,AdapterView中有一个内部类AdapterDataSetObserver,在ListView设置Adapter时会构建一个AdapterDataSetObserver,并且注册到Adapter中,这个就是一个观察者。而Adapter中包含一个数据集可观察者DataSetObservable,在数据数量发生变更时开发者手动调用Adapter中notifyDataSetChanged函数,而notifyDataSetChanged实际上会调用DataSetObservable的notifyChanged函数,该函数会遍历所有观察者的onChanged函数。在AdapterDataSetObserver的onChanged函数中会获取Adapter中数据集的新数量,然后调用ListView的requestLayout()方法重新进行布局,更新用户界面。

4. 参考文档

ListView与设计模式:

http://blog.csdn.net/smllys0000/article/details/51064543
http://blog.csdn.net/bboyfeiyu/article/details/44040533
http://blog.csdn.net/bboyfeiyu/article/details/43950185
https://github.com/simple-android-framework-exchange/android_design_patterns_analysis

ListView优化:
https://www.jianshu.com/p/728e031f1a74
https://www.zhihu.com/question/19703384
http://niorgai.github.io/2014/12/13/ListView%E4%B8%8EBaseAdapter%E4%BC%98%E5%8C%96/
http://blog.csdn.net/like_program/article/details/52901492

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值