1. 程式人生 > >ListView在removeFooterView時報java.lang.ClassCastException錯問題

ListView在removeFooterView時報java.lang.ClassCastException錯問題

自古英雄不問出處,奈何我卻不是英雄!

這些天遇到一個很奇怪的問題,很奇怪的問題,很奇怪的問題。重要的事情要說三遍。奇怪的問題大都是在解決之間很奇怪,如果你解決之後你會發現奇怪的是你自己。下面我來說一下我是怎麼奇怪了一把的。

這個奇怪的問題(其實不奇怪)是跟ListView有關係。先說問題和解決辦法:java.lang.Class Cast Exception: android.widget.HeaderViewListAdapter這麼一個異常。那麼你就要看看你的listView.addFooterView是不是放在了listView.setAdaptr後面了。咋辦呢,把它放前面就好了。

下面來說說出問題的願意,這裡有一個HeaderViewListAdapter,首先你回想:這是什麼鬼。沒見過這個類,哪裡來的轉換異常。下面咱們看一下原始碼:

    @Override
    public void setAdapter(ListAdapter adapter) {
        

        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
            mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
        } else {
            mAdapter = adapter;
        }
    
    }
這段程式碼是listView中的原始碼,原始碼有很多行,不過咱們不用看,就這一段就可以。有木有發現HeaderViewListAdapter這個鬼。這裡的if判斷中的mHeaderViewInfos和mFooterViewInfos就是咱們加的listView的header和footer。至於.size()這個方法,咱們暫且理解為你是否為listView add過header或者footer。稍後再來詳細說明一下。想必大家能夠理解了,如果你設定了header或者footer中的其中一個,就會New出一個HeaderViewListAdapter,然後傳入三個引數分別是header和footer和你傳入的adapter。沒設定的話就直接是你建立的那個adapter了。下面看這段原始碼:
    public boolean removeFooterView(View v) {
        if (mFooterViewInfos.size() > 0) {
            boolean result = false;
            if (mAdapter != null && ((HeaderViewListAdapter) mAdapter).removeFooter(v)) {
                if (mDataSetObserver != null) {
                    mDataSetObserver.onChanged();
                }
                result = true;
            }
            removeFixedViewInfo(v, mFooterViewInfos);
            return result;
        }
        return false;
    }
看到沒有。listView呼叫的的時候是HeaderViewListAdapter來執行的,由於你沒有先設定header或者footer,導致adapter還是原來的,並不是HeaderViewListAdapter。結果就會出現咱們遇到的類轉換異常了。

-------------------這裡是分割線,下面的已經和問題無關,這裡只做拓展----------------------

下面再來說一下上面提到的mHeaderViewInfos.size()和mFooterViewInfos.size()。這裡只是來說明為什麼是.size(),而不是用是否為null來判斷,咱們還是來看原始碼:

/**
     * A class that represents a fixed view in a list, for example a header at the top
     * or a footer at the bottom.
     */
    public class FixedViewInfo {
        /** The view to add to the list */
        public View view;
        /** The data backing the view. This is returned from {@link ListAdapter#getItem(int)}. */
        public Object data;
        /** <code>true</code> if the fixed view should be selectable in the list */
        public boolean isSelectable;
    }
    private ArrayList<FixedViewInfo> mHeaderViewInfos = Lists.newArrayList();
    private ArrayList<FixedViewInfo> mFooterViewInfos = Lists.newArrayList();

看到了吧,這裡是new出來的,咋能用null判斷呢。

再來往下看addHeaderView和addFooterView之後,會走原始碼中的下面這兩個方法:

    public void addHeaderView(View v) {
        addHeaderView(v, null, true);
    }
    public void addFooterView(View v) {
        addFooterView(v, null, true);
    }
大家能看到這兩個方法什麼事都沒幹,只是呼叫了相同方法名的方法,並且傳入了三個引數,其實這兩個方法我們也是可以直接呼叫的,只是不掉用也是沒有任何問題的。下面咱們來說說這三個引數是做什麼的。還是看原始碼:!- -!
    public void addHeaderView(View v, Object data, boolean isSelectable) {
        final FixedViewInfo info = new FixedViewInfo();
        info.view = v;
        info.data = data;
        info.isSelectable = isSelectable;
        mHeaderViewInfos.add(info);
        // Wrap the adapter if it wasn't already wrapped.
        if (mAdapter != null) {
            if (!(mAdapter instanceof HeaderViewListAdapter)) {
                mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
            }
            // In the case of re-adding a header view, or adding one later on,
            // we need to notify the observer.
            if (mDataSetObserver != null) {
                mDataSetObserver.onChanged();
            }
        }
    }
由於addFooterView和addHeaderView非常類似,這裡我就補貼程式碼了。咱們主要來說明這三個引數是什麼。

第一個引數:View v,我就不多說了,就是咱們傳進來的View。

第二個引數:Object data,這個就是你header中的資料,你傳入之後在點選header的時候可以用getItem(int)這個方法獲取出來。當然也是可以不傳的,咱們是可以通過別的方法做出和點選同樣效果的,我就不說了,大家都懂得。

第三個引數:boolean isSelectabe,簡單來說,就是為了讓header或者footer可不可點的,true就是能點選,索引就是0。false就是不能點選了

------------------這裡是分割線,拓展結束------------------

好了就這麼多。希望對大家有用。