Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 4.4以下ListView addHeader和addFooter放在setAdapter之後導致異常的原因分析和解決

Android 4.4以下ListView addHeader和addFooter放在setAdapter之後導致異常的原因分析和解決

編輯:關於Android編程

問題重現:

在Android 19之前,ListView的addHeader和addFooter必須在setAdapter之前調用,否則就會有異常,Android 19以及之後是沒有這個問題的。異常的具體表現為:
1.在setAdapter之後調用mListView.addHeaderView(mHeader);會拋出異常:
Cannot add header view to list -- setAdapter has already been called.
2.在setAdapter之後調用mListView.addFooterView(mFooter);雖然不會拋出異常,但是卻看不到添加的footer。

問題解決:

在Android 19之前,如果想在setAdapter之後添加header和footer,可以這樣做:

//設置adapter之後設置header和footer
        ListAdapter originalAdapter; //得到之前給listview設置的adapter,如果已經知道,可以不用
        if (mListView.getAdapter() instanceof HeaderViewListAdapter) {
            HeaderViewListAdapter headerViewListAdapter = (HeaderViewListAdapter) mListView.getAdapter();
            originalAdapter = headerViewListAdapter.getWrappedAdapter();
        } else {
            originalAdapter = mListView.getAdapter();
        }
        mListView.setAdapter(null);
        mListView.addHeaderView(mHeader);
        mListView.addFooterView(mFooter);
        mListView.setAdapter(originalAdapter);

問題原因

我們可以對比Android 18和19的ListView的源碼,在addHeaderView的改變:

API 18
public void addHeaderView(View v, Object data, boolean isSelectable) {

    if (mAdapter != null && ! (mAdapter instanceof HeaderViewListAdapter)) {
        throw new IllegalStateException(
                "Cannot add header view to list -- setAdapter has already been called.");
    }

    FixedViewInfo info = new FixedViewInfo();
    info.view = v;
    info.data = data;
    info.isSelectable = isSelectable;
    mHeaderViewInfos.add(info);

    // in the case of re-adding a header view, or adding one later on,
    // we need to notify the observer
    if (mAdapter != null && mDataSetObserver != null) {
        mDataSetObserver.onChanged();
    }
}
API 19
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();
        }
    }
}

可以看到,在Android 19之前,如果ListView設置過Adapter,會拋出異常,在Android 19中,google做了調整。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved