在我一直在努力的应用程序中,我有一个自定义类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