Search code examples
androidrealmandroid-spinner

Searchable Spinner combined with Realm


I have implemented SearchableSpinner to my project. It's inside an Fragment.

I'm using Realm as the database. In my onCreateView method I have this...

@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.ncrdocument, container, false);
    realm = Realm.getDefaultInstance();
    documents = new ArrayList<>();
    documents = realm.where(MaterialDoc.class).findAll();
    ArrayAdapter<MaterialDoc> adapter = new ArrayAdapter<>(this.getContext(), android.R.layout.simple_list_item_1, documents);
    matList.setAdapter(adapter);
.
.
.
return view;

The data loads fine, it shows them correctly, but when I try to search the spinner, my app crashes and I get this error.

An exception occured during performFiltering()
java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created
at io.realm.BaseRealm.checkIfValid(BaseRealm.java:383)
at io.realm.MaterialDocRealmProxy.realmGet$document_number(MaterialDocRealmProxy.java:126)
at com.my.application.test.Model.MaterialDoc.getDocumentNumber(MaterialDoc.java:29)
at com.my.application.test.Model.MaterialDoc.toString(MaterialDoc.java:42)
at android.widget.ArrayAdapter$ArrayFilter.performFiltering(ArrayAdapter.java:480)
at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.os.HandlerThread.run(HandlerThread.java:61)
01-09 12:13:06.649 18606-18606/com.my.application.test D/AndroidRuntime: Shutting down VM
01-09 12:13:06.669 18606-18606/com.my.application.test E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.my.application.test, PID: 18606
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
at android.widget.ArrayAdapter.getCount(ArrayAdapter.java:330)
at android.widget.AdapterView.checkFocus(AdapterView.java:947)
at android.widget.AdapterView$AdapterDataSetObserver.onInvalidated(AdapterView.java:1070)
at android.widget.AbsListView$AdapterDataSetObserver.onInvalidated(AbsListView.java:8297)
at android.database.DataSetObservable.notifyInvalidated(DataSetObservable.java:50)
at android.widget.BaseAdapter.notifyDataSetInvalidated(BaseAdapter.java:59)
at android.widget.ArrayAdapter$ArrayFilter.publishResults(ArrayAdapter.java:513)
at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6939)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)

Solution

  • You have to be careful when you deal with realmresults across threads. The realm results from one thread you can't use in some other. So try to get a copy of your result set (Which is detached from active realm instance) and give this copy to your adapter. Realm has copyFromRealm method for doing this.

    Modify your code like this

        Realm realm = Realm.getDefaultInstance();
        RealmResults<MaterialDoc> realmResults = realm.where(MaterialDoc.class).findAll();
        List<MaterialDoc> documents = realm.copyFromRealm(realmResults);
        ArrayAdapter<MaterialDoc> adapter = new ArrayAdapter<>(this.getContext(), android.R.layout.simple_list_item_1, documents);
        matList.setAdapter(adapter);