grishka / appkit

Android app boilerplate + image loader
50 stars 17 forks source link

Null pointer exception in recyclerView #12

Closed LucasGGamerM closed 9 months ago

LucasGGamerM commented 9 months ago
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean androidx.recyclerview.widget.RecyclerView$ViewHolder.shouldIgnore()' on a null object reference
                                                                                                        at androidx.recyclerview.widget.RecyclerView.findMinMaxChildLayoutPositions(RecyclerView.java:4476)
                                                                                                        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:4206)
                                                                                                        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4001)
                                                                                                        at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1991)
                                                                                                        at androidx.recyclerview.widget.RecyclerView.focusSearch(RecyclerView.java:2922)
                                                                                                        at android.view.ViewGroup.focusSearch(ViewGroup.java:1080)
                                                                                                        at android.view.ViewGroup.focusSearch(ViewGroup.java:1080)
                                                                                                        at android.view.ViewGroup.focusSearch(ViewGroup.java:1080)
                                                                                                        at android.view.View.focusSearch(View.java:13286)
                                                                                                        at android.widget.TextView.hasEditorInFocusSearchDirection(TextView.java:8996)
                                                                                                        at android.widget.TextView.onCreateInputConnection(TextView.java:9016)
                                                                                                        at android.view.inputmethod.InputMethodManager.startInputInner(InputMethodManager.java:2308)
                                                                                                        at android.view.inputmethod.InputMethodManager$DelegateImpl.startInput(InputMethodManager.java:666)
                                                                                                        at android.view.ImeFocusController.checkFocus(ImeFocusController.java:167)
                                                                                                        at android.view.inputmethod.InputMethodManager.checkFocus(InputMethodManager.java:2507)
                                                                                                        at android.view.inputmethod.InputMethodManager.showSoftInput(InputMethodManager.java:1869)
                                                                                                        at android.view.inputmethod.InputMethodManager.showSoftInput(InputMethodManager.java:1856)
                                                                                                        at android.view.inputmethod.InputMethodManager.showSoftInput(InputMethodManager.java:1794)
                                                                                                        at org.joinmastodon.android.fragments.discover.SearchQueryFragment.onShown(SearchQueryFragment.java:283)
                                                                                                        at me.grishka.appkit.fragments.AppKitFragment.onResume(AppKitFragment.java:546)
                                                                                                        at android.app.Fragment.performResume(Fragment.java:2551)
                                                                                                        at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1346)
                                                                                                        at android.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1581)
                                                                                                        at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1642)
                                                                                                        at android.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2220)
         org...stodon.android.moshinda.debug  E     at android.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2166)
                                                                                                        at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2067)
                                                                                                        at android.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:822)
                                                                                                        at me.grishka.appkit.FragmentStackActivity.showFragment(FragmentStackActivity.java:122)
                                                                                                        at me.grishka.appkit.Nav.goForResult(Nav.java:57)
grishka commented 9 months ago

I have seen this before but I have no idea why this could happen

LucasGGamerM commented 9 months ago

Me neither. I stumbled upon this when I was upgrading appkit on Moshidon to finally be able to get rid of my janky emptyView incorrect coloring situation. Sadly the app is now rather unstable

grishka commented 9 months ago

Sadly the app is now rather unstable

There were other crashes that I fixed in today's update.

I have an idea about this one now though — it might be related to focus handling. Are you able to reproduce it at least somewhat reliably?

LucasGGamerM commented 9 months ago

Sadly the app is now rather unstable

There were other crashes that I fixed in today's update.

I have an idea about this one though. Are you able to reproduce it at least somewhat reliably?

Yes. The main source of the crash is on opening the search on Moshidon. But I have indeed confirmed it also crashes on the stock Mastodon app. Its not always, but its a lot

grishka commented 9 months ago

Oh wow. It's crashing in the profile pager adapter when you open a search fragment. That's really bizarre. image

(btw this issue belongs to the Mastodon app repo, but TIL that issues can only be moved within the same user/organization)

LucasGGamerM commented 9 months ago

Oh wow. It's crashing in the profile pager adapter when you open a search fragment. That's really bizarre. image

(btw this issue belongs to the Mastodon app repo, but TIL that issues can only be moved within the same user/organization)

Well, I did some testing and the crashes stop when I go back to the 1.2.9 version of appkit. But they are always there when I am using 1.2.11

grishka commented 9 months ago

I fixed it. I'm not proud of how, but I did.

LucasGGamerM commented 9 months ago

The fix didn't fix it. Even after updating to the latest git version and using appkit version 1.2.12, the error still remains.

Here are the logs:


FATAL EXCEPTION: main
                 Process: org.joinmastodon.android.moshinda.debug, PID: 13567
                 java.lang.RuntimeException: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean androidx.recyclerview.widget.RecyclerView$ViewHolder.shouldIgnore()' on a null object reference
                    at me.grishka.appkit.Nav.goForResult(Nav.java:60)
                    at org.joinmastodon.android.fragments.discover.DiscoverFragment.openSearch(DiscoverFragment.java:206)
                    at org.joinmastodon.android.fragments.HomeFragment.onTabSelected(HomeFragment.java:273)
                    at org.joinmastodon.android.fragments.HomeFragment.$r8$lambda$b18Tv4BBIlnJafkgLJbHzB76hi0(Unknown Source:0)
                    at org.joinmastodon.android.fragments.HomeFragment$$ExternalSyntheticLambda1.accept(Unknown Source:2)
                    at org.joinmastodon.android.ui.views.TabBar.onChildClick(TabBar.java:45)
                    at org.joinmastodon.android.ui.views.TabBar.$r8$lambda$-HlfNq01unHCQKJIzbfzuMwRjG8(Unknown Source:0)
                    at org.joinmastodon.android.ui.views.TabBar$$ExternalSyntheticLambda0.onClick(Unknown Source:2)
                    at android.view.View.performClick(View.java:7542)
                    at android.view.View.performClickInternal(View.java:7519)
                    at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0)
                    at android.view.View$PerformClick.run(View.java:29476)
                    at android.os.Handler.handleCallback(Handler.java:942)
                    at android.os.Handler.dispatchMessage(Handler.java:99)
                    at android.os.Looper.loopOnce(Looper.java:201)
                    at android.os.Looper.loop(Looper.java:288)
                    at android.app.ActivityThread.main(ActivityThread.java:7924)
                    at java.lang.reflect.Method.invoke(Native Method)
                    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
                 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean androidx.recyclerview.widget.RecyclerView$ViewHolder.shouldIgnore()' on a null object reference
                    at androidx.recyclerview.widget.RecyclerView.findMinMaxChildLayoutPositions(RecyclerView.java:4476)
                    at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:4206)
                    at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4001)
                    at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1991)
                    at androidx.recyclerview.widget.RecyclerView.focusSearch(RecyclerView.java:2922)
                    at android.view.ViewGroup.focusSearch(ViewGroup.java:1080)
                    at android.view.ViewGroup.focusSearch(ViewGroup.java:1080)
                    at android.view.ViewGroup.focusSearch(ViewGroup.java:1080)
                    at android.view.View.focusSearch(View.java:13286)
                    at android.widget.TextView.hasEditorInFocusSearchDirection(TextView.java:8996)
                    at android.widget.TextView.onCreateInputConnection(TextView.java:9016)
                    at android.view.inputmethod.InputMethodManager.startInputInner(InputMethodManager.java:2308)
                    at android.view.inputmethod.InputMethodManager$DelegateImpl.startInput(InputMethodManager.java:666)
                    at android.view.ImeFocusController.checkFocus(ImeFocusController.java:167)
                    at android.view.inputmethod.InputMethodManager.checkFocus(InputMethodManager.java:2507)
                    at android.view.inputmethod.InputMethodManager.showSoftInput(InputMethodManager.java:1869)
                    at android.view.inputmethod.InputMethodManager.showSoftInput(InputMethodManager.java:1856)
                    at android.view.inputmethod.InputMethodManager.showSoftInput(InputMethodManager.java:1794)
                    at org.joinmastodon.android.fragments.discover.SearchQueryFragment.onShown(SearchQueryFragment.java:283)
                    at me.grishka.appkit.fragments.AppKitFragment.onResume(AppKitFragment.java:546)
                    at android.app.Fragment.performResume(Fragment.java:2551)
                    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1346)
                    at android.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1581)
                    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1642)
                    at android.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2220)
09:09:19.359  E     at android.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2166)
                    at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2067)
                    at android.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:822)
                    at me.grishka.appkit.FragmentStackActivity.showFragment(FragmentStackActivity.java:122)
                    at me.grishka.appkit.Nav.goForResult(Nav.java:57)
                    ... 19 more

As always, I tested this both on 1.2.9, 1.2.10, 1.2.11 and 1.2.12. Only 1.2.9 works as expected

grishka commented 9 months ago

I still insist that this isn't related to appkit

grishka commented 9 months ago

Actually, my latest fixes made the issue worse 🙈

After looking at all the code that could possibly be involved with this crash, I now have a suspicion that RecyclerView REALLY doesn't like me reusing views like that: https://github.com/mastodon/mastodon-android/blob/1724d8a532bf00eb44b030d33087ab672b4b3a61/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java#L1053-L1059

I'll try rewriting that part.

LucasGGamerM commented 9 months ago

I still insist that this isn't related to appkit

Well, I am not sure how it's not related to appkit. The crash happens when there is a call to Nav.go, which is an appkit method

grishka commented 9 months ago

But it's a rethrown exception that happens when initializing a fragment.

grishka commented 9 months ago

Now I'm sure I fixed it. The thing I was doing with removing views to reuse straight from RecyclerView must've been messing up some internal RecyclerView state really bad.

LucasGGamerM commented 9 months ago

It didn't fix it. Here is the crash log I get every time I try to open the search inside Moshidon (my Mastodon android app fork):

FATAL EXCEPTION: main
                 Process: org.joinmastodon.android.moshinda.debug, PID: 9754
                 java.lang.NullPointerException: Attempt to invoke virtual method 'boolean androidx.recyclerview.widget.RecyclerView$ViewHolder.shouldIgnore()' on a null object reference
                    at androidx.recyclerview.widget.RecyclerView.findMinMaxChildLayoutPositions(RecyclerView.java:4476)
                    at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:4206)
                    at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4001)
                    at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4569)
                    at android.view.View.layout(View.java:23798)
                    at android.view.ViewGroup.layout(ViewGroup.java:6413)
                    at androidx.viewpager2.widget.ViewPager2.onLayout(ViewPager2.java:523)
                    at android.view.View.layout(View.java:23798)
                    at android.view.ViewGroup.layout(ViewGroup.java:6413)
                    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1891)
                    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1729)
                    at android.widget.LinearLayout.onLayout(LinearLayout.java:1638)
                    at android.view.View.layout(View.java:23798)
                    at android.view.ViewGroup.layout(ViewGroup.java:6413)
                    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1891)
                    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1729)
                    at android.widget.LinearLayout.onLayout(LinearLayout.java:1638)
                    at android.view.View.layout(View.java:23798)
                    at android.view.ViewGroup.layout(ViewGroup.java:6413)
                    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
                    at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
                    at android.view.View.layout(View.java:23798)
                    at android.view.ViewGroup.layout(ViewGroup.java:6413)
                    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1891)
                    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1729)
                    at android.widget.LinearLayout.onLayout(LinearLayout.java:1638)
                    at android.view.View.layout(View.java:23798)
                    at android.view.ViewGroup.layout(ViewGroup.java:6413)
                    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
                    at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
                    at android.view.View.layout(View.java:23798)
                    at android.view.ViewGroup.layout(ViewGroup.java:6413)
                    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
                    at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
                    at android.view.View.layout(View.java:23798)
                    at android.view.ViewGroup.layout(ViewGroup.java:6413)
                    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
                    at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
                    at android.view.View.layout(View.java:23798)
                    at android.view.ViewGroup.layout(ViewGroup.java:6413)
                    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
                    at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
                    at android.view.View.layout(View.java:23798)
                    at android.view.ViewGroup.layout(ViewGroup.java:6413)
                    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
                    at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
                    at com.android.internal.policy.DecorView.onLayout(DecorView.java:799)
                    at android.view.View.layout(View.java:23798)
                    at android.view.ViewGroup.layout(ViewGroup.java:6413)
                    at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:4118)
                    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3459)
                    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2371)
                    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9297)
                    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1231)
                    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)
                    at android.view.Choreographer.doCallbacks(Choreographer.java:899)
                    at android.view.Choreographer.doFrame(Choreographer.java:832)
                    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214)
                    at android.os.Handler.handleCallback(Handler.java:942)
                    at android.os.Handler.dispatchMessage(Handler.java:99)
14:45:06.817  E     at android.os.Looper.loopOnce(Looper.java:201)
                    at android.os.Looper.loop(Looper.java:288)
                    at android.app.ActivityThread.main(ActivityThread.java:7924)
                    at java.lang.reflect.Method.invoke(Native Method)
                    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
grishka commented 9 months ago

Did you just update appkit, or did you update the Mastodon sources too?

grishka commented 9 months ago

I was able to reliably reproduce the crash by opening the search, closing it, then opening again. It no longer crashes.

LucasGGamerM commented 9 months ago

Did you just update appkit, or did you update the Mastodon sources too?

I just updated appkit. Is there anything I am missing?

grishka commented 9 months ago

Of course that won't fix anything. I told you this wasn't an appkit bug. The appkit update fixes an unrelated ArrayIndexOutOfBoundsException that I found in Google Play console.

LucasGGamerM commented 9 months ago

I am sorry for the misunderstanding. Still, is there anything I can do to fix that crash? I have no clue on how to go about it

grishka commented 9 months ago

Just sync your app sources with the upstream. Or just cherry-pick commit 283b56be5b5bc4bedfcb87156a26ff5a99fe6c5a