ListView setAdapter has already been called 異常
阿新 • • 發佈:2019-01-05
本文參考:http://blog.csdn.net/androiddevelop/article/details/8474939
異常提示:Java.lang.IllegalStateException: Cannot add header view to list -- setAdapter has already been called.
產生原因:addHeaderView()呼叫在setAdapter()之後,並且該程式碼執行在Android4.3之前的系統版本。Android SDK與API Level對應表
我們來看看(Android4.3)API-18 和 (Android4.2)API-17的Listview
API-18
public void addHeaderView(View v, Object data, boolean isSelectable) { 02. final FixedViewInfo info = new FixedViewInfo(); 03. info.view = v; 04. info.data = data; 05. info.isSelectable = isSelectable; 06. mHeaderViewInfos.add(info); 07. 08. // Wrap the adapter if it wasn't already wrapped. 09. if (mAdapter != null) { 10. if (!(mAdapter instanceof HeaderViewListAdapter)) { 11. mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter); 12. } 13. 14. // In the case of re-adding a header view, or adding one later on, 15. // we need to notify the observer. 16. if (mDataSetObserver != null) { 17. mDataSetObserver.onChanged(); 18. } 19. } 20.}
API-17
public void addHeaderView(View v, Object data, boolean isSelectable) { 02. 03. if (mAdapter != null && ! (mAdapter instanceof HeaderViewListAdapter)) { 04. throw new IllegalStateException( 05. "Cannot add header view to list -- setAdapter has already been called."); 06. } 07. 08. FixedViewInfo info = new FixedViewInfo(); 09. info.view = v; 10. info.data = data; 11. info.isSelectable = isSelectable; 12. mHeaderViewInfos.add(info); 13. 14. // in the case of re-adding a header view, or adding one later on, 15. // we need to notify the observer 16. if (mAdapter != null && mDataSetObserver != null) { 17. mDataSetObserver.onChanged(); 18. } 19.}
在API-17中,假如adapter不為空,則會直接丟擲異常,而在API-18中則做了相關的優化。
再看一下setAdapter()方法部分原始碼:
public void More ...setAdapter(ListAdapter adapter) {
...此處省略部分程式碼...
if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}
...此處省略部分程式碼...
}
建議
按照正常的人邏輯:先新增header,在4.3以前版本,由於此時mAdapter = null,所以不會走拋異常邏輯。再設定adapter,此時看adapter的原始碼,此時的adapter成為了HeaderListAdapter了,我們在此時可以移除掉header。
等在訪問網路成功之後,再去新增header,此時走進addHeader的原始碼,雖然if語句中mAdapter!=null條件滿足,但是後面條件mAdapter已經是HeaderListAdapter型別了,條件不滿足,也不會走拋異常邏輯。此時就是可行的。
總結:先新增header或者footer,在setAdapter之後再移除掉header或者footer。在訪問網路成功之後,再去新增header或者footer即可。