一:BaseAdapter介紹 BaseAdapter是listview,gridview等列表,使用的數據適配器,它的主要用途是將一組數據傳到ListView、Spinner、Gallery及GridView等UI顯示組件,如果listView列表的數據項過多,如1000項,我們如果把這1000項 ...
一:BaseAdapter介紹
BaseAdapter是listview,gridview等列表,使用的數據適配器,它的主要用途是將一組數據傳到ListView、Spinner、Gallery及GridView等UI顯示組件,如果listView列表的數據項過多,如1000項,我們如果把這1000項全部放到界面中去,軟體直接記憶體溢出了,BaseAdapter剛纔可以幫我們解決這個問題,BaseAdapter工作原理圖如下:
從上圖中看出,如果我們有1000個數據項,實際顯示的只有7項,其它的緩存在Recycler中,Recycler類似於消息對列,用來保存未顯示在ui上的數據項,如果頂部(或底部)通過滾動,從listView界面中滑出,Recycler就將該數據項,添加到消息對列,如上圖中,第一項已經從界面中滑出,當第一項重新滑進的時候,android會判斷第一項是否載入過,如果有那麼就重新設置第一項的數據源,然後顯示。當第一次載入數據項,或者上滑,或者下滑顯示數據項的時候,就會調用getView()方法,然而很多時候,getView()方法系統會調用多次,調用多次就會多次刷新界面,性能會降低,比如界面會卡頓等。
/** @params position 需要顯示的數據下標,從0開始 @params view 顯示的視圖 @ViewGroup 視圖的組 */ public View getView(int position, View view, ViewGroup viewGroup)
二:解決辦法
1:網上常用的方法
<ListView android:id="@+id/lv_messages" android:layout_width="fill_parent" android:layout_height="fill_parent" > </ListView>
網上說執行多次原因是因為每顯示一個VIew,它都去測量view的高度,執行measure方法,導致getView執行多次,但該listView嵌套在ScrollView時,BaseAdapter的getView()方法一樣會調用多次。
2:重寫ListView的onMeasure和onLayout方法。
我重寫ListView的onMeasure和onLayout方法,定義一個,是否第一載入的變數boolean isOnMeasure=false,然後在BastAdapter的getView方法,判斷是否第一次載入界面,通過這個方法來處理這個問題.
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { isOnMeasure = true; int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { isOnMeasure = false; super.onLayout(changed, l, t, r, b); }
三:完整代碼
1:重寫listView
public class ScrollListView extends ListView { private boolean isOnMeasure; public boolean isMeasure() { return isOnMeasure; } public ScrollListView(Context context) { super(context); } public ScrollListView(Context context, AttributeSet attrs) { super(context, attrs); } public ScrollListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { isOnMeasure = true; int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); // super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { isOnMeasure = false; super.onLayout(changed, l, t, r, b); } }
2:activity的xml
<view.ScrollListView android:id="@+id/orderGoodsList" style="@style/list_normal" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_below="@id/line3" android:background="@color/gray_f2" android:divider="@color/gray_f2" android:dividerHeight="1dip" > </view.ScrollListView>
3:適配器代碼
protected ViewGroup viewGroup; @Override public void initData(View view, Object viewHolder, int position) { if (!((BaseGridView) viewGroup).isMeasure()) { //第一次載入,處理界面ui }else{ //不是第一次載入,不處理任何事 } }
如果你有更好的方法,也請你留下分享一下你的方法,謝謝!