android 分享一個處理BaseAdapter,getView()多次載入的方法,baseadaptergetview
一: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{ //不是第一次載入,不處理任何事 } }
如果你有更好的方法,也請你留下分享一下你的方法,謝謝!