在我一直在努力的應用程序中,我有一個自定義類DeviceListAdapter
擴展BaseAdapter
它被傳遞到我的ListView
。在我的DeviceListAdapter
課堂上,我保留我自己的ArrayList<Device>
,我用它來生成View getView(...)
的列表視圖。每當應用程序導致數據更改時,我使用DeviceListAdapter
中的自定義方法更新ArrayList<Device>
以反映更改。我已經使用調試器和許多打印語句來檢查數據是否按預期的方式發生了變化,如指定的那樣添加和刪除Device
對象。但是,在每次更改數據後,我還會調用notifyDataSetChanged()
,但在UI上沒有任何元素會更新。在調試器中,我發現調用notifyDataSetChanged()
之後,getView(...)
方法未被調用,這就解釋了爲什麼ListView
未被重繪。爲了弄清楚爲什麼,我使用調試器的「step into」函數來跟蹤程序執行進入android框架的位置,因爲我已經下載了SDK源代碼。我發現的非常有趣。執行的路徑是這樣的:Android的ListView適配器錯誤調用notifyDataSetChanged,Android的錯誤?
DeviceListAdapter.notifyDataSetChanged()
BaseAdapter.notifyDataSetChanged()
DataSetObservable.notifyChanged()
AbsListView.onInvalidated()
而是調用onChanged()
方法,它跳下軌道,一旦達到AbsListView
執行onInvalidated()
方法。最初我以爲這是一個錯誤的調試器可能讀錯了行號,但我重新啓動我的Android Studio以及完全卸載並重新安裝應用程序,但結果是一樣的。任何人都可以告訴我,如果這是Android框架的合法問題,或者如果調試器對於在自己的項目文件之外追蹤執行不可靠?
更多關於我的執行notifyDataSetChanged()
...我創建的本地方法重寫BaseAdapter
的notifyDataSetChanged()
,這樣我可以設置一個布爾標誌mForceRedraw
我DeviceListAdapter
內,以我是否應該強制重繪我的列表條目。在getView(...)
方法中,我通常會檢查第二個參數View convertView
是否爲空,如果是,則重繪視圖,如果不是,則傳遞convertView並返回它。但是,當'mForceRedraw'爲true時,我從不返回convertView
,我明確地重繪視圖。出現的問題是由於我以前的擔心造成的,即執行notifyDataSetChanged()
後不會調用getView()
。
編輯:這是我的一個DeviceListAdapter
代碼片段:
/**
* Serves data about current Device data to the mDeviceListView. Manages the dynamic and
* persistent storage of the configured Devices and constructs views of each individual
* list item for placement in the list.
*/
private class DeviceListAdapter extends BaseAdapter {
private boolean mForceRedraw = false;
/**
* Dynamic array that keeps track of all devices currently being managed.
* This is held in memory and is readily accessible so that system calls
* requesting View updates can be satisfied quickly.
*/
private List<Device> mDeviceEntries;
private Context mContext;
public DeviceListAdapter(Context context) {
this.mContext = context;
this.mDeviceEntries = new ArrayList<>();
populateFromStorage();
}
/**
* Inserts the given device into storage and notifies the mDeviceListView of a data update.
* @param newDevice The device to add to memory.
*/
public void put(Device newDevice) {
Preconditions.checkNotNull(newDevice);
boolean flagUpdatedExisting = false;
for (Device device : mDeviceEntries) {
if (newDevice.isVersionOf(device)) {
int index = mDeviceEntries.indexOf(device);
if(index != -1) {
mDeviceEntries.set(index, newDevice);
flagUpdatedExisting = true;
break;
} else {
throw new IllegalStateException();
}
}
//If an existing device was not updated, then this is a new device, add it to the list
if (!flagUpdatedExisting) {
mDeviceEntries.add(newDevice);
}
TECDataAdapter.setDevices(mDeviceEntries);
notifyDataSetChanged();
}
/**
* If the given device exists in storage, delete it and remove it from the mDeviceListView.
* @param device
*/
public void delete(Device device) {
Preconditions.checkNotNull(device);
//Remove device from mDeviceEntries
Iterator iterator = mDeviceEntries.iterator();
while(iterator.hasNext()) {
Device d = (Device) iterator.next();
if(device.isVersionOf(d)) {
iterator.remove();
}
}
TECDataAdapter.setDevices(mDeviceEntries);
notifyDataSetChanged();
}
/**
* Retrieves Device entries from persistent storage and loads them into the dynamic
* array responsible for displaying the entries in the listView.
*/
public void populateFromStorage() {
List<Device> temp = Preconditions.checkNotNull(TECDataAdapter.getDevices());
mDeviceEntries = temp;
notifyDataSetChanged();
}
public int getCount() {
if (mDeviceEntries != null) {
return mDeviceEntries.size();
}
return 0;
}
public Object getItem(int position) {
return mDeviceEntries.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
LinearLayout view;
if (convertView == null || mForceRedraw) //Regenerate the view
{
/* Draws my views */
} else //Reuse the view
{
view = (LinearLayout) convertView;
}
return view;
}
@Override
public void notifyDataSetChanged() {
mForceRedraw = true;
super.notifyDataSetChanged();
mForceRedraw = false;
}
}
你可以給你的應用程序代碼段? – Kushal