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