android 分享一個處理BaseAdapter,getView()多次加載的方法


一: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{
                    //不是第一次加載,不處理任何事
                }     
}       

 

 

如果你有更好的方法,也請你留下分享一下你的方法,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM