Table closed in Adapter.

71 views
Skip to first unread message

Mark Andrachek, Jr.

unread,
Jun 9, 2015, 10:50:22 AM6/9/15
to realm...@googlegroups.com
I've got an application I've converted using to realm, and it's working pretty well so far, except for one edge case.

I've got an activity that's got a master-detail view, and in the case of a phone, the master and detail are separate activities.  This is using a recycler view, basically as outlined here - http://gradlewhy.ghost.io/realm-results-with-recyclerview/ - I've run into a situation though that apparently if the back button is hit fast enough when going from the first activity to the second, getItemCount fails.

06-09 10:18:57.033    6129-6129/com.seguehealth.community.debug E/null Illegal state exception trying to get item count.
    java
.lang.IllegalStateException: Illegal State: Table is closed, and no longer valid to operate on.
            at io
.realm.internal.TableView.nativeSize(Native Method)
            at io
.realm.internal.TableView.size(TableView.java:129)
            at io
.realm.RealmResults.size(RealmResults.java:305)
            at io
.realm.RealmBaseAdapter.getCount(RealmBaseAdapter.java:65)
            at com
.myapp.MyAdapter.getItemCount(MyAdapter.java:58)
            at android
.support.v7.widget.RecyclerView$LayoutManager.getRowCountForAccessibility(RecyclerView.java:7469)
            at android
.support.v7.widget.RecyclerView$LayoutManager.onInitializeAccessibilityNodeInfo(RecyclerView.java:7344)
            at android
.support.v7.widget.RecyclerView$LayoutManager.onInitializeAccessibilityNodeInfo(RecyclerView.java:7304)
            at android
.support.v7.widget.RecyclerViewAccessibilityDelegate.onInitializeAccessibilityNodeInfo(RecyclerViewAccessibilityDelegate.java:59)
            at android
.support.v4.view.AccessibilityDelegateCompat$AccessibilityDelegateJellyBeanImpl$1.onInitializeAccessibilityNodeInfo(AccessibilityDelegateCompat.java:233)
            at android
.support.v4.view.AccessibilityDelegateCompatJellyBean$1.onInitializeAccessibilityNodeInfo(AccessibilityDelegateCompatJellyBean.java:61)
            at android
.view.View.onInitializeAccessibilityNodeInfo(View.java:5525)
            at android
.view.View.createAccessibilityNodeInfoInternal(View.java:5488)
            at android
.view.View$AccessibilityDelegate.createAccessibilityNodeInfo(View.java:20854)
            at android
.view.View.createAccessibilityNodeInfo(View.java:5473)
            at android
.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1064)
            at android
.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchAccessibilityNodeInfos(AccessibilityInteractionController.java:888)
            at android
.view.AccessibilityInteractionController.findAccessibilityNodeInfoByAccessibilityIdUiThread(AccessibilityInteractionController.java:155)
            at android
.view.AccessibilityInteractionController.access$400(AccessibilityInteractionController.java:53)
            at android
.view.AccessibilityInteractionController$PrivateHandler.handleMessage(AccessibilityInteractionController.java:1236)
            at android
.os.Handler.dispatchMessage(Handler.java:102)
            at android
.os.Looper.loop(Looper.java:135)
            at android
.app.ActivityThread.main(ActivityThread.java:5254)
            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:898)
            at com
.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)

At least for now, I'm trapping the error and handling it in my getItemCount() -
@Override
public int getItemCount() {
   
try {
       
if (getRealmAdapter() != null) {
           
return getRealmAdapter().getCount();
       
}
   
}
   
catch (IllegalStateException ise) {
       
// I know the realm is closed here, it gets reset in onResume.
   
}
   
return 0;
}


I've tried checking .first().isValid() - however that seems to fail with an index out of bounds exception, and .isEmpty() throws the same IllegalStateException.

Obviously I could forgo the second activity all-together and use a FragmentTransaction adding to the backstack instead. 

Other than that, is there a better way of dealing with this? 

Mark Andrachek, Jr.

unread,
Jun 9, 2015, 11:19:43 AM6/9/15
to realm...@googlegroups.com
So, I've got another issue. This gets around the crash, however once I've gone from Activity A w/ RecyclerView fragment to Activity B with detail view fragment, everything looks good, but as soon as I scroll I get the dreaded java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 11(offset:11).state:30. :(

Christian Melchior

unread,
Jun 10, 2015, 1:58:29 AM6/10/15
to Mark Andrachek Jr., realm...@googlegroups.com
Hi Mark

You are getting the "Table is closed" error because the Realm backing your query result has been closed. I am not sure you how/when you close your Realm instance, but moving it to the Activity lifecycle (onCreate/onDestroy) for your master/detail activity would probably solve this issue?

Note that Realm internally uses a thread local cache for detecting when a Realm should be fully closed:

Realm.getInstance() -> Count: 1
RealmResults query = doQuery();
Realm.getInstance() -> Count: 2
Realm.close() -> Count: 1 (Realm instance is still alive)
query.get(0) -> Can still access query results.
Realm.close() -> Count: 0 (Realm is closed completely)
query.get(0) -> It will now crash with a "closed" exception.

--
Christian Melchior
Senior Android Developer


--
You received this message because you are subscribed to the Google Groups "Realm Java" group.
To unsubscribe from this group and stop receiving emails from it, send an email to realm-java+...@googlegroups.com.
To post to this group, send email to realm...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/realm-java/2c700e7e-530c-487a-a757-80f71da9568e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



{#HS:96643185-1292#}

Mark R. Andrachek, Jr.

unread,
Jun 10, 2015, 8:15:24 AM6/10/15
to Christian Melchior, realm...@googlegroups.com

The realm life cycle is tied to the activity life cycle for both activities. The first thing done in OnCreate (after super.OnCreate()) is to get an instance, the last thing done in onDestroy is to close it. In fact they both extend the same base activity class that handles this for them.

When two activities are involved (master activity and detail activity) with fragments (master fragment, detail fragment), with a recyclerview in the master fragment, and adapter configured as per the URL (the fragment gets the realm from the activity), the crash occurs when rapidly cycling between activities.

The id value from the selected item in master view is passed to the detail activity.  The detail fragment gets the realm from the activity, and looks up the item to populate the UI.

Fragments do not have retainInstance set.

I would expect getReamAdapter() to be null.

I will try and replicate outside my codebase, and send you the code that exercises this.

I've already gone ahead and moved to a single monolithic activity to work around this.

Kenneth Geisshirt

unread,
Jun 23, 2015, 2:45:55 AM6/23/15
to Mark R. Andrachek Jr., realm...@googlegroups.com
Hi Mark,

Have you been able to replicate the issue outside your codebase? If so, can you share it?

Best,
Kenneth

--
Kenneth Geisshirt
Member of technical staff
{#HS:96643185-1292#}
Reply all
Reply to author
Forward
0 new messages