Android-适配器的内容已更改?
我试图让我的无休止的列表工作,但我一直得到关于修改适配器内容的非法状态异常。我完全不知道为什么会这样 这个错误很严重Android-适配器的内容已更改?,android,listview,android-asynctask,Android,Listview,Android Asynctask,我试图让我的无休止的列表工作,但我一直得到关于修改适配器内容的非法状态异常。我完全不知道为什么会这样 这个错误很严重 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
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)]
以下是我的任务:
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);
}
}
及
所以我认为可能是两个任务在同一个适配器上工作。因此,我修改了onscroll
方法中if
语句的最后一部分,这减少了崩溃的数量,但我仍然有一些
编辑:@Elltz的Logcat
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)
好的,在分析代码之后,这似乎是一个有效的解决方案,请尝试以下方法: 1.将此方法添加到适配器
public void addNewData(ArrayList<News> newData) {
if(news != null) {
news.addAll(newData);
notifyDataSetChanged();
}
}
希望这会有所帮助
编辑显然它不起作用,所以最后的办法是更改适配器
public class ListNewsAdapter extends BaseAdapter {
private final ArrayList<News> news;
private View progressView;
NewsListFragment fragment;
LayoutInflater inflater;
public ListNewsAdapter(Context context, NewsListFragment fragment) {
this.fragment = fragment;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
if(news == null)
return 0;
return NewsListFragment.isLoading() ? news.size() + 1 : news.size();
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
try {
if (convertView == null || convertView.findViewById(R.id.title) != null || convertView == progressView) {
convertView = inflater.inflate(R.layout.news_list_row, 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 = getItem(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;
}
}
@Override
public News getItem(int position) {
return news.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
static class ViewHolder {
TextView title;
TextView description;
ImageView image;
}
public void addNewData(ArrayList<News> newData) {
if(news == null) {
news = new ArrayList<News>();
}
news.addAll(newData);
notifyDataSetChanged();
}
}
我希望我没有遗漏任何我刚刚手写的东西,我没有Eclipse。这个列表是只加载一次,还是不断得到新结果?@DroidChris:list得到了新结果(一旦用户滚动到底部,就会得到一些旧消息)@iravivooda:第一组项被放入适配器的构造函数。显示适配器class@ElJazouli完成,编辑完成。没有任何变化。也许是因为这个观点?我已经把它关掉了,看起来它现在可以工作了。。。
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)
public void addNewData(ArrayList<News> newData) {
if(news != null) {
news.addAll(newData);
notifyDataSetChanged();
}
}
@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.addNewData(result.getNewsArray());
isLoading = false;
}
super.onPostExecute(result);
}
public class ListNewsAdapter extends BaseAdapter {
private final ArrayList<News> news;
private View progressView;
NewsListFragment fragment;
LayoutInflater inflater;
public ListNewsAdapter(Context context, NewsListFragment fragment) {
this.fragment = fragment;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
if(news == null)
return 0;
return NewsListFragment.isLoading() ? news.size() + 1 : news.size();
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
try {
if (convertView == null || convertView.findViewById(R.id.title) != null || convertView == progressView) {
convertView = inflater.inflate(R.layout.news_list_row, 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 = getItem(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;
}
}
@Override
public News getItem(int position) {
return news.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
static class ViewHolder {
TextView title;
TextView description;
ImageView image;
}
public void addNewData(ArrayList<News> newData) {
if(news == null) {
news = new ArrayList<News>();
}
news.addAll(newData);
notifyDataSetChanged();
}
}
@Override
protected void onPostExecute(NewsArrayList result) {
mLeftToDownload = result.getLeft();
ListNewsAdapter adapter = (ListNewsAdapter) listView.getAdapter();
if (adapter == null) {
adapter = new ListNewsAdapter(getActivity(), NewsListFragment.this);
listView.setAdapter(adapter);
}
adapter.addNewData(result.getNewsArray());
isLoading = false;
super.onPostExecute(result);
}