Android - Realm - Object delete - Object is no longer valid to operate on -
i'm trying delete item recyclerview
populated realm
database , i'm getting following error:
java.lang.illegalstateexception: illegal state: object no longer valid operate on. deleted thread?
assumptions guess i'm trying access when it's deleted, don't understand where.
context: i'm showing list of cities , longclicking on item shows dialog asking confirm deletion.
the item deleted in database since when relaunch app, it's not there anymore.
realm arraylist
public static arraylist<city> getstoredcities(){ realmquery<city> query = getrealminstance().where(city.class); final realmresults<city>results = realm.where(city.class) .findallsorted("timestamp", sort.descending); results.size(); arraylist<city> cityarraylist = new arraylist<>(); for(int = 0; i< results.size(); i++){ cityarraylist.add(results.get(i)); } return cityarraylist; }
dialog code
builder.setpositivebutton(getstring(r.string.ok), new dialoginterface.onclicklistener() { @override public void onclick(dialoginterface dialoginterface, int i) { realmhelper.removecity(cityarraylist.get(position)); cityarraylist.remove(position); mrecyclerview.removeviewat(position); mcitylistadapter.notifyitemremoved(position); mcitylistadapter.notifyitemrangechanged(position, cityarraylist.size()); mcitylistadapter.notifydatasetchanged(); } });
realm method delete item
public static void removecity(city city){ realmresults<city> result = realm.where(city.class).equalto("cityname", city.getcityname()).findall(); realm.begintransaction(); result.deleteallfromrealm(); realm.committransaction(); }
logs
07-28 11:02:08.461 9461-9461/com.ilepez.weatherapp e/androidruntime: fatal exception: main process: com.ilepez.weatherapp, pid: 9461 java.lang.illegalstateexception: illegal state: object no longer valid operate on. deleted thread? @ io.realm.internal.uncheckedrow.nativegetstring(native method) @ io.realm.internal.uncheckedrow.getstring(uncheckedrow.java:153) @ io.realm.cityrealmproxy.realmget$cityname(cityrealmproxy.java:75) @ com.ilepez.weatherapp.data.model.city.getcityname(city.java:41) @ com.ilepez.weatherapp.adapter.citylistadapter.onbindviewholder(citylistadapter.java:56) @ com.ilepez.weatherapp.adapter.citylistadapter.onbindviewholder(citylistadapter.java:20) @ android.support.v7.widget.recyclerview$adapter.onbindviewholder(recyclerview.java:5768) @ android.support.v7.widget.recyclerview$adapter.bindviewholder(recyclerview.java:5801) @ android.support.v7.widget.recyclerview$recycler.getviewforposition(recyclerview.java:5037) @ android.support.v7.widget.recyclerview$recycler.getviewforposition(recyclerview.java:4913) @ android.support.v7.widget.linearlayoutmanager$layoutstate.next(linearlayoutmanager.java:2029) @ android.support.v7.widget.linearlayoutmanager.layoutchunk(linearlayoutmanager.java:1414) @ android.support.v7.widget.linearlayoutmanager.fill(linearlayoutmanager.java:1377) @ android.support.v7.widget.linearlayoutmanager.onlayoutchildren(linearlayoutmanager.java:588) @ android.support.v7.widget.recyclerview.dispatchlayoutstep2(recyclerview.java:3260) @ android.support.v7.widget.recyclerview.onmeasure(recyclerview.java:2788) @ android.view.view.measure(view.java:20151) @ android.view.viewgroup.measurechildwithmargins(viewgroup.java:6328) @ android.widget.framelayout.onmeasure(framelayout.java:194) @ android.support.design.widget.navigationview.onmeasure(navigationview.java:218) @ android.view.view.measure(view.java:20151) @ android.support.v4.widget.drawerlayout.onmeasure(drawerlayout.java:1108) @ android.view.view.measure(view.java:20151) @ android.view.viewgroup.measurechildwithmargins(viewgroup.java:6328) @ android.widget.framelayout.onmeasure(framelayout.java:194) @ android.support.v7.widget.contentframelayout.onmeasure(contentframelayout.java:135) @ android.view.view.measure(view.java:20151) @ android.view.viewgroup.measurechildwithmargins(viewgroup.java:6328) @ android.widget.linearlayout.measurechildbeforelayout(linearlayout.java:1464) @ android.widget.linearlayout.measurevertical(linearlayout.java:747) @ android.widget.linearlayout.onmeasure(linearlayout.java:629) @ android.view.view.measure(view.java:20151) @ android.view.viewgroup.measurechildwithmargins(viewgroup.java:6328) @ android.widget.framelayout.onmeasure(framelayout.java:194) @ android.view.view.measure(view.java:20151) @ android.view.viewgroup.measurechildwithmargins(viewgroup.java:6328) @ android.widget.linearlayout.measurechildbeforelayout(linearlayout.java:1464) @ android.widget.linearlayout.measurevertical(linearlayout.java:747) @ android.widget.linearlayout.onmeasure(linearlayout.java:629) @ android.view.view.measure(view.java:20151) @ android.view.viewgroup.measurechildwithmargins(viewgroup.java:6328) @ android.widget.framelayout.onmeasure(framelayout.java:194) @ com.android.internal.policy.phonewindow$decorview.onmeasure(phonewindow.java:3158) @ android.view.view.measure(view.java:20151) @ android.view.viewrootimpl.performmeasure(viewrootimpl.java:2594) @ android.view.viewrootimpl.measurehierarchy(viewrootimpl.java:1549) @ android.view.viewrootimpl.performtraversals(viewrootimpl.java:1841) @ android.view.viewrootimpl.dotraversal(viewrootimpl.java:1437) @ android.view.viewrootimpl$traversalrunnable.run(viewrootimpl.java:7403) @ android.view.choreographer$callbackrecord.run(choreographer.java:920) @ android.view.choreographer.docallbacks(choreographer.java:695) @ android.view.choreographer.doframe(choreographer.java:631) @ android.view.choreographer$framedisplayeventreceiver.run(choreographer.java:906) @ android.os.handler.handlecall
adapter code
public class citylistadapter extends recyclerview.adapter<citylistadapter.citylistviewholder>{ public interface onitemclicklistener{ void onitemclick(int position); } public interface onitemlongclicklistener{ void onitemlongclick(int position); } private static final string log_tag = citylistadapter.class.getsimplename(); private arraylist<city> cityarraylist = new arraylist<>(); private context mcontext; private onitemclicklistener onitemclicklistener; private onitemlongclicklistener onitemlongclicklistener; public citylistadapter(context context, arraylist<city> cityarraylist, onitemclicklistener onitemclicklistener, onitemlongclicklistener onitemlongclicklistener) { this.cityarraylist = cityarraylist; this.mcontext = context; this.onitemclicklistener = onitemclicklistener; this.onitemlongclicklistener = onitemlongclicklistener; } @override public citylistviewholder oncreateviewholder(viewgroup parent, int viewtype) { view view = layoutinflater.from(parent.getcontext()).inflate(r.layout.city_item_navigation_viewholder, null); citylistviewholder citylistviewholder = new citylistviewholder(view, parent.getcontext()); return citylistviewholder; } @override public void onbindviewholder(citylistviewholder holder, int position) { holder.cityname.settext(cityarraylist.get(position).getcityname()); holder.bindclick(position, onitemclicklistener); holder.bindlongclick(position, onitemlongclicklistener); } @override public int getitemcount() { return cityarraylist.size(); } public class citylistviewholder extends recyclerview.viewholder{ textview cityname; imageview cityicon; public citylistviewholder(view itemview, context context) { super(itemview); cityname = (textview)itemview.findviewbyid(r.id.city_name); cityicon = (imageview)itemview.findviewbyid(r.id.city_icon); } public void bindclick(final int position, final onitemclicklistener onitemclicklistener){ itemview.setonclicklistener(new view.onclicklistener() { @override public void onclick(view view) { onitemclicklistener.onitemclick(position); } }); } public void bindlongclick(final int position, final onitemlongclicklistener onitemlongclicklistener) { itemview.setonlongclicklistener(new view.onlongclicklistener() { @override public boolean onlongclick(view view) { onitemlongclicklistener.onitemlongclick(position); return true; } }); } } }
okay you're calling adapter.notifydatasetchanged()
, other notify___
method unnecessary (data set change disables animations anyways.)
in case easiest (and efficient) way of doing things use realmresults
directly rather retrieving every element arraylist
used exact same way.
so should this
public static realmresults<city> getstoredcities(){ realmquery<city> query = getrealminstance().where(city.class); return realm.where(city.class) .findallsorted("timestamp", sort.descending); }
and
public static void removecity(city city){ final string cityname = city.getcityname(); realm.executetransaction(new realm.transaction() { @override public void execute(realm realm) { realmresults<city> result = realm.where(city.class).equalto("cityname", cityname).findall(); result.deleteallfromrealm(); } }); }
and
builder.setpositivebutton(getstring(r.string.ok), new dialoginterface.onclicklistener() { @override public void onclick(dialoginterface dialoginterface, int i) { realmhelper.removecity(getitem(position)); } });
and
// dependency: compile 'io.realm:android-adapters:1.3.0' // <-- realm 3.x+, use 2.0.0 public class citylistadapter extends realmrecyclerviewadapter<city, citylistviewholder> { onitemclicklistener onitemclicklistener; onitemlongclicklistener onitemlongclicklistener; public citylistadapter(@nonnull context context, @nullable orderedrealmcollection<city> data, onitemclicklistener onitemclicklistener, onitemlongclicklistener onitemlongclicklistener) { super(context, data, true); this.onitemclicklistener = onitemclicklistener; this.onitemlongclicklistener = onitemlongclicklistener; } @override public citylistviewholder oncreateviewholder(viewgroup parent, int viewtype) { view view = layoutinflater.from(parent.getcontext()).inflate(r.layout.city_item_navigation_viewholder, parent, false); citylistviewholder citylistviewholder = new citylistviewholder(view, parent.getcontext()); return citylistviewholder; } @override public void onbindviewholder(citylistviewholder holder, int position) { holder.cityname.settext(getitem(position).getcityname()); holder.bindclick(position, onitemclicklistener); holder.bindlongclick(position, onitemlongclicklistener); } public static class citylistviewholder extends recyclerview.viewholder { textview cityname; imageview cityicon; public citylistviewholder(view itemview, context context) { super(itemview); cityname = (textview)itemview.findviewbyid(r.id.city_name); cityicon = (imageview)itemview.findviewbyid(r.id.city_icon); } public void bindclick(final int position, final onitemclicklistener onitemclicklistener){ itemview.setonclicklistener(new view.onclicklistener() { @override public void onclick(view view) { onitemclicklistener.onitemclick(position); } }); } public void bindlongclick(final int position, final onitemlongclicklistener onitemlongclicklistener) { itemview.setonlongclicklistener(new view.onlongclicklistener() { @override public boolean onlongclick(view view) { onitemlongclicklistener.onitemlongclick(position); return true; } }); } } }
using realmrecyclerviewadapter
call notifydatasetchanged()
whenever results change.
Comments
Post a Comment