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與設計模式: