我试图让我无尽的列表工作,但所有的时间我得到有关修改适配器的内容IllegalStateException。我完全不知道为什么会发生。Android - 适配器的内容已更改?
错误是相当
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(2131493058, class android.widget.ListView) with Adapter(class ListNewsAdapter)]
这里是我的AsyncTask:
public class ListDownloadNewAsyncTask extends AsyncTask<Void, Void, NewsArrayList> {
private String mLastId = null;
@Override
protected void onPreExecute() {
ListNewsAdapter adapter = (ListNewsAdapter) listView.getAdapter();
if (adapter != null && adapter.getCount() > 0) {
mLastId = adapter.getItem(adapter.getCount() - 1).getId();
}
super.onPreExecute();
}
@Override
protected NewsArrayList doInBackground(Void... params) {
NewsArrayList downloadedNews = null;
try {
downloadedNews = JSONLoader.loadNews(getActivity(), mLastId);
} catch (Exception ex) { }
return downloadedNews;
}
@Override
protected void onPostExecute(NewsArrayList result) {
mLeftToDownload = result.getLeft();
ListNewsAdapter adapter = (ListNewsAdapter) listView.getAdapter();
if (adapter == null) {
adapter = new ListNewsAdapter(getActivity(), R.layout.news_list_row, result.getNewsArray(), NewsListFragment.this);
listView.setAdapter(adapter);
} else {
adapter.addAll(result.getNewsArray());
adapter.notifyDataSetChanged();
isLoading = false;
}
super.onPostExecute(result);
}
}
我正在寻找不已的ListView任何代码片段,但我发现大部分事情是静态或动态创建- 未下载。
所以我的问题是......我在这里错过了什么?或者我做错了什么?
编辑:这是我的适配器类
public class ListNewsAdapter extends ArrayAdapter<News> {
private final ArrayList<News> news;
private final int newsRowResourceId;
private View progressView;
NewsListFragment fragment;
public ListNewsAdapter(Context context, int newsRowResourceId, ArrayList<News> news, NewsListFragment fragment) {
super(context, newsRowResourceId, news);
this.news = news;
this.newsRowResourceId = newsRowResourceId;
this.fragment = fragment;
}
@Override
public int getCount() {
return NewsListFragment.isLoading() ? news.size() + 1 : news.size();
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewHolder holder;
try {
if (convertView == null || convertView.findViewById(R.id.title) != null || convertView == progressView) {
convertView = inflater.inflate(newsRowResourceId, null);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.title);
holder.description = (TextView) convertView.findViewById(R.id.description);
holder.image = (ImageView) convertView.findViewById(R.id.news_list_item_image);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if (position < getCount()) {
News newsRow = news.get(position);
if (newsRow != null) {
holder.title.setText(newsRow.getTitle().trim().replaceAll("[\n\r]", " "));
holder.description.setText(newsRow.getDescription().trim().replaceAll("[\n\r]", " "));
if (newsRow.getPhotoUrl() != null && !newsRow.getPhotoUrl().equalsIgnoreCase("null")) {
Ion.with(holder.image).placeholder(R.drawable.icon).load(newsRow.getPhotoUrl());
} else {
holder.image.setImageResource(R.drawable.icon);
}
}
}
convertView.setClickable(true);
convertView.setFocusable(true);
convertView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Main.instance.changeNewsFragment(news.get(position).getNewsUrl());
}
});
return convertView;
} catch (IndexOutOfBoundsException e) {
progressView = inflater.inflate(R.layout.progress_list_item, null);
return progressView;
}
}
static class ViewHolder {
TextView title;
TextView description;
ImageView image;
}
}
编辑:我想到了一两件事。我认为推出从的AsyncTask OnScrollListener:
public abstract class InfiniteScrollListener implements AbsListView.OnScrollListener {
private int bufferItemCount = 10;
public InfiniteScrollListener(int bufferItemCount) {
this.bufferItemCount = bufferItemCount;
}
public abstract void loadMore();
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if ((mLeftToDownload > 0) && !isLoading && ((firstVisibleItem + visibleItemCount) >= (totalItemCount - bufferItemCount))) {
Log.d("test", "from onScroll: " + mLeftToDownload + ", " + isLoading + ", " + (firstVisibleItem + visibleItemCount) + ">=" + (totalItemCount - bufferItemCount));
isLoading = true;
loadMore();
}
}
}
和
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.news_list_fragment, null);
listView = (ListView) v.findViewById(R.id.list_news);
mLeftToDownload = -1;
listView.setOnScrollListener(new InfiniteScrollListener(5) {
@Override
public void loadMore() {
new ListDownloadNewAsyncTask().execute();
}
});
listView.setItemsCanFocus(true);
new ListDownloadNewAsyncTask().execute();
return v;
}
所以,我认为它可能是用相同的适配器上工作的两个任务。所以我修改了onscroll
方法中的if
声明的最后部分,这减少了崩溃的数量,但我仍然有一些。
编辑:logcat的用于@Elltz
05-12 00:58:51.027 5108-5108/app.packg E/AndroidRuntime﹕ FATAL EXCEPTION: main
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(2131493058, class android.widget.ListView) with Adapter(class ListNewsAdapter)]
at android.widget.ListView.layoutChildren(ListView.java:1538)
at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:4385)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
at android.view.Choreographer.doCallbacks(Choreographer.java:555)
at android.view.Choreographer.doFrame(Choreographer.java:524)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4849)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
at dalvik.system.NativeStart.main(Native Method)
此列表仅加载一次,还是不断得到新的结果? –
@DroidChris:列表正在获得新的结果(一旦用户滚动到底部,获得几个旧的新闻)。 – Seraphis
@iRaviiVooda:第一组物品放在适配器的构造函数中。 – Seraphis