listview - Android - content of the adapter has changed? -
i'm trying endless list working time illegalstateexception modifying content of adapter. have totally no clue why happens.
the error pretty
illegalstateexception: content of adapter has changed listview did not receive notification. make sure content of adapter not modified background thread, ui thread. [in listview(2131493058, class android.widget.listview) adapter(class listnewsadapter)]
here 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); } }
i searching code snippet endless listview, things have found static or dynamically created - not downloaded.
so question is... have missed here? or doing wrong?
edit: here adapter class
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; } }
edit: thought 1 more thing. launching 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(); } } }
and
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; }
and thought might 2 tasks working on same adapter. have modify last part of if
statement in onscroll
method , reduced amount of crashes still have some.
edit: logcat @elltz
05-12 00:58:51.027 5108-5108/app.packg e/androidruntime﹕ fatal exception: main java.lang.illegalstateexception: content of adapter has changed listview did not receive notification. make sure content of adapter not modified background thread, ui thread. [in listview(2131493058, class android.widget.listview) adapter(class listnewsadapter)] @ android.widget.listview.layoutchildren(listview.java:1538) @ android.widget.abslistview$flingrunnable.run(abslistview.java:4385) @ android.view.choreographer$callbackrecord.run(choreographer.java:725) @ android.view.choreographer.docallbacks(choreographer.java:555) @ android.view.choreographer.doframe(choreographer.java:524) @ android.view.choreographer$framedisplayeventreceiver.run(choreographer.java:711) @ android.os.handler.handlecallback(handler.java:615) @ android.os.handler.dispatchmessage(handler.java:92) @ android.os.looper.loop(looper.java:137) @ android.app.activitythread.main(activitythread.java:4849) @ java.lang.reflect.method.invokenative(native method) @ java.lang.reflect.method.invoke(method.java:511) @ com.android.internal.os.zygoteinit$methodandargscaller.run(zygoteinit.java:795) @ com.android.internal.os.zygoteinit.main(zygoteinit.java:562) @ dalvik.system.nativestart.main(native method)
ok, after analysing code, seems working solution, try this:
1.add method adapter
public void addnewdata(arraylist<news> newdata) { if(news != null) { news.addall(newdata); notifydatasetchanged(); } }
2.replace onpostexecute
this
@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); }
hope
edit apparently didn't work, last resort change adapter
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(); } }
and replace onpostexecute
@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); }
i hope i'm not missing wrote hand don't have eclipse on me.
Comments
Post a Comment