Android 安卓ArrayAdapter。“适配器的内容已更改,但ListView未收到通知。”
我对listview有问题。某些用户发生以下跟踪的崩溃:Android 安卓ArrayAdapter。“适配器的内容已更改,但ListView未收到通知。”,android,listview,android-arrayadapter,Android,Listview,Android Arrayadapter,我对listview有问题。某些用户发生以下跟踪的崩溃: java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thr
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(16908298, class android.widget.ListView) with Adapter(class com.a.b.c)]
at android.widget.ListView.layoutChildren(ListView.java:1779)
at android.widget.AbsListView.onTouchEvent(AbsListView.java:3264)
at android.widget.ListView.onTouchEvent(ListView.java:4098)
at android.view.View.dispatchTouchEvent(View.java:5568)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2069)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1737)
at android.widget.AbsListView.dispatchTouchEvent(AbsListView.java:6272)
at android.widget.ListView.dispatchTouchEvent(ListView.java:4820)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2075)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1751)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2075)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1751)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2075)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1751)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2075)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1751)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2075)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1751)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2075)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1751)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1998)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1410)
at android.app.Activity.dispatchTouchEvent(Activity.java:2433)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1946)
at android.view.View.dispatchPointerEvent(View.java:5748)
at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3170)
at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2724)
at android.view.ViewRootImpl.processInputEvents(ViewRootImpl.java:951)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:965)
at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2700)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:5109)
但我确信ArrayList中的内容没有改变。代码:
public class ArchivedEventListFragment extends ListFragment {
ArrayList<Event> mEvents;
...
EventArrayAdapter mEventsAdapter;
DataManager mDataManager;
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
mDataManager = DataManager.get(getActivity());
...
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.archive_list_fragment, container, false);
...
return view;
}
@Override
public void onResume() {
super.onResume();
if (mEvents == null) {
mEvents = mDataManager.getArchivedEvents();
if (mEvents.isEmpty()) {
new DownloadArchive().execute();
} else if (mEventsAdapter == null) {
mEventsAdapter = new EventArrayAdapter(mEvents);
setListAdapter(mEventsAdapter);
} else if (getListAdapter() == null) {
setListAdapter(mEventsAdapter);
} else {
mEventsAdapter.notifyDataSetChanged();
}
}
if (getListAdapter() != null && mEventsAdapter != null) {
mEventsAdapter.notifyDataSetChanged();
}
getListView().clearChoices();
...
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
...
}
static class ViewHolderItem {
...
}
private class EventArrayAdapter extends ArrayAdapter<Event> {
private final ArrayList<Event> events;
public EventArrayAdapter(ArrayList<Event> sourceEvents) {
super(getActivity(), 0, sourceEvents);
events = sourceEvents;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolderItem viewHolder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.event_list_item, parent, false);
...
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolderItem) convertView.getTag();
}
Event event = getItem(position);
...
return convertView;
}
@Override
public int getCount() {
return events.size();
}
@Override
public Event getItem(int position) {
return events.get(position);
}
}
private class DownloadArchive extends AsyncTask<Void, Void, ArrayList<Event>> {
@Override
protected ArrayList<Event> doInBackground(Void... params) {
return mDataManager.getArchivedEvents();
}
@Override
protected void onPreExecute() {
setListAdapter(null);
mEventsAdapter = null;
super.onPreExecute();
}
@Override
protected void onPostExecute(ArrayList<Event> result) {
super.onPostExecute(result);
if (isAdded()) {
mEvents = result;
if (!(mEvents.isEmpty())) {
mEventsAdapter = new EventArrayAdapter(mEvents);
setListAdapter(mEventsAdapter);
} else {
try {
Toast.makeText(getActivity(), "Error", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
}
mDataManager.clearEvents();
new DownloadArchive().execute();
}
}
}
}
...
}
我尝试在代码中的任何地方调用adpater.notifydatasetchanget,但没有任何帮助。请帮助我了解哪里是我的错。我对程序中的逻辑有很多问题。如果你愿意,我可以检查一下。但是,既然你问了一个具体的问题,我就在这里做一些假设。似乎您有一些存储事件的单例对象数据管理器。我认为正在发生的是,在其他地方,在其他类中,您正在修改mDataManager中的事件。因为那里的事件列表支持适配器中存储的事件列表,所以Android抱怨您在没有通知的情况下更新了列表。我向DataManager询问了一次事件,并将它们保存在新的ArrayList中。在这段代码中,为什么DataManager ArrayList中的更改可能会影响ArrayList?我希望您了解一点java。关键是,实际上您可能只创建了一个ArrayList。你有多少次新的ArrayList?可能只有在DataManager中。在您发布的代码中,您从未实际创建过新的ArrayList。因此,这里的适配器实际上在使用DataManager中的ArrayList。如果您在其他任何地方,在任何其他代码中更新该ArrayList,都会在这里产生问题。我认为ArrayList mEvents;mEvents=mDataManager.getArchivedEvents;创建一个新的ArrayList并从DataManager复制数据。实际上,它并不创建新的列表,mEvents只指向DataManager返回的ArrayList。假设您有对象o1=新对象,对象o2=o1。显然,只有一个对象,只有一个新语句。o2只是指向与o1相同的对象。这就是你的情况。