CarouselView icon indicating copy to clipboard operation
CarouselView copied to clipboard

[BUG][Android] Crash when CarouselView is nested in a ScrollView, inside a TabViewItem (XCT)

Open Kapusch opened this issue 4 years ago • 6 comments
trafficstars

Description

Hello @alexrainman , I have been using your component for a few months, after I've got rid off the official CarouselView (so many events issues...) and I have to say : thank you very much for your great library !

But the thing is I am now using the Xamarin.CommunityToolkit (XCT) library so that I can navigate to my pages with bottom tabs. And my app is getting crashed every time I try to display your CarouselView inside a ScrollView.

I am actually having a java.lang.StackOverflowError :

Expand Stacktrace
[Mono] Assembly Ref addref CarouselView.FormsPlugin.Droid[0xce8f4de0] -> Java.Interop[0xce5c9d80]: 22
[w_stackoverflo] java_vm_ext.cc:570] JNI DETECTED ERROR IN APPLICATION: JNI GetObjectClass called with pending exception java.lang.StackOverflowError: stack size 8192KB
[w_stackoverflo] java_vm_ext.cc:570]   at void crc6414252951f3f66c67.CarouselViewAdapter_2.n_onBindViewHolder(androidx.recyclerview.widget.RecyclerView$ViewHolder, int) (CarouselViewAdapter_2.java:-2)
[w_stackoverflo] java_vm_ext.cc:570]   at void crc6414252951f3f66c67.CarouselViewAdapter_2.onBindViewHolder(androidx.recyclerview.widget.RecyclerView$ViewHolder, int) (CarouselViewAdapter_2.java:38)
[w_stackoverflo] java_vm_ext.cc:570]   at void androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(androidx.recyclerview.widget.RecyclerView$ViewHolder, int, java.util.List) (RecyclerView.java:7065)
[w_stackoverflo] java_vm_ext.cc:570]   at void androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(androidx.recyclerview.widget.RecyclerView$ViewHolder, int) (RecyclerView.java:7107)
[w_stackoverflo] java_vm_ext.cc:570]   at boolean androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(androidx.recyclerview.widget.RecyclerView$ViewHolder, int, int, long) (RecyclerView.java:6012)
[w_stackoverflo] java_vm_ext.cc:570]   at androidx.recyclerview.widget.RecyclerView$ViewHolder androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(int, boolean, long) (RecyclerView.java:6279)
[w_stackoverflo] java_vm_ext.cc:570]   at android.view.View androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(int, boolean) (RecyclerView.java:6118)
[w_stackoverflo] java_vm_ext.cc:570]   at android.view.View androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(int) (RecyclerView.java:6114)
[w_stackoverflo] java_vm_ext.cc:570]   at android.view.View androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(androidx.recyclerview.widget.RecyclerView$Recycler) (LinearLayoutManager.java:2303)
[w_stackoverflo] java_vm_ext.cc:570]   at void androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(androidx.recyclerview.widget.RecyclerView$Recycler, androidx.recyclerview.widget.RecyclerView$State, androidx.recyclerview.widget.LinearLayoutManager$LayoutState, androidx.recyclerview.widget.LinearLayoutManager$LayoutChunkResult) (LinearLayoutManager.java:1627)
[w_stackoverflo] java_vm_ext.cc:570]   at int androidx.recyclerview.widget.LinearLayoutManager.fill(androidx.recyclerview.widget.RecyclerView$Recycler, androidx.recyclerview.widget.LinearLayoutManager$LayoutState, androidx.recyclerview.widget.RecyclerView$State, boolean) (LinearLayoutManager.java:1587)
[w_stackoverflo] java_vm_ext.cc:570]   at void androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(androidx.recyclerview.widget.RecyclerView$Recycler, androidx.recyclerview.widget.RecyclerView$State) (LinearLayoutManager.java:640)
[w_stackoverflo] java_vm_ext.cc:570]   at void androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2() (RecyclerView.java:4134)
[w_stackoverflo] java_vm_ext.cc:570]   at void androidx.recyclerview.widget.RecyclerView.dispatchLayout() (RecyclerView.java:3851)
[w_stackoverflo] java_vm_ext.cc:570]   at void androidx.recyclerview.widget.RecyclerView$Adapter.bindViewH03-13 12:05:07.875 F/w_stackoverflo(12828): java_vm_ext.cc:570]   at void androidx.recyclerview.widget.RecyclerView.onLayout(boolean, int, int, int, int) (RecyclerView.java:4404)
[w_stackoverflo] java_vm_ext.cc:570]   at void crc643f46942d9dd1fff9.ItemsViewRenderer_3.n_onLayout(boolean, int, int, int, int) (ItemsViewRenderer_3.java:-2)
[w_stackoverflo] java_vm_ext.cc:570]   at void crc643f46942d9dd1fff9.ItemsViewRenderer_3.onLayout(boolean, int, int, int, int) (ItemsViewRenderer_3.java:45)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.View.layout(int, int, int, int) (View.java:22160)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6402)
[w_stackoverflo] 03-13 12:05:07.875 F/w_stackoverflo(12828): java_vm_ext.cc:570]   at void crc643f46942d9dd1fff9.Platform_DefaultRenderer.n_onLayout(boolean, int, int, int, int) (Platform_DefaultRenderer.java:-2)
[w_stackoverflo] java_vm_ext.cc:570]   at void crc643f46942d9dd1fff9.Platform_DefaultRenderer.onLayout(boolean, int, int, int, int) (Platform_DefaultRenderer.java:72)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.View.layout(int, int, int, int) (View.java:22160)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6402)
[w_stackoverflo] java_vm_ext.cc:570]   at void androidx.recyclerview.widget03-13 12:05:07.875 F/w_stackoverflo(12828): java_vm_ext.cc:570]   at void crc643f46942d9dd1fff9.Platform_DefaultRenderer.n_onLayout(boolean, int, int, int, int) (Platform_DefaultRenderer.java:-2)
[w_stackoverflo] java_vm_ext.cc:570]   at void crc643f46942d9dd1fff9.Platform_DefaultRenderer.onLayout(boolean, int, int, int, int) (Platform_DefaultRenderer.java:72)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.View.layout(int, int, int, int) (View.java:22160)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6402)
[w_stackoverflo] java_vm_ext.cc:570]   at void com.xamarin.forms.platform.android.FormsViewGroup.measureAndLayout(int, int, int, int, int, int) (FormsViewGroup.java:37)
[w_stackoverflo] java_vm_ext.cc:570]   at void crc643f46942d9dd1fff9.ItemsViewRenderer_3.onLayout(boolean, int, int, int, int) (ItemsViewRend:07.875 F/w_stackoverflo(12828): java_vm_ext.cc:570]   at void crc643f46942d9dd1fff9.PageRenderer.n_onLayout(boolean, int, int, int, int) (PageRenderer.java:-2)
[w_stackoverflo] java_vm_ext.cc:570]   at void crc643f46942d9dd1fff9.PageRenderer.onLayout(boolean, int, int, int, int) (PageRenderer.java:72)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.View.layout(int, int, int, int) (View.java:22160)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6402)
[w_stackoverflo] java_vm_ext.cc:570]   at void com.xamarin.forms.platform.android.FormsViewGroup.measureAndLayout(int, int, int, int, int, int) (FormsViewGroup.java:37)
[w_stackoverflo] java_vm_ext.cc:570]   at void crc643f46942d9dd1fff9.PlatformRenderer.n_onLayout(boolean, int, int, int, int) (PlatformRenderer.java:-2)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.View.layout(int, int, int, int) (View.java:22160)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6402)
[w_stackoverflo] java_vm_03-13 12:05:07.875 F/w_stackoverflo(12828): java_vm_ext.cc:570]   at void android.widget.RelativeLayout.onLayout(boolean, int, int, int, int) (RelativeLayout.java:1103)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.View.layout(int, int, int, int) (View.java:22160)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6402)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.View.layout(int, int, int, int) (View.java:22160)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6402)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.widget.FrameLayout.layoutChildren(int, int, int, int, boolean) (FrameLayout.java:332)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.widget.FrameLayout.onLayout(boolean, int, int, int, int) (FrameLayout.java:270)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.View.layout(int, int, int, int) (View.java:22160)
[w_stackoverfl03-13 12:05:07.876 F] java_vm_ext.cc:570]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6402)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.widget.FrameLayout.layoutChildren(int, int, int, int, boolean) (FrameLayout.java:332)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.widget.FrameLayout.onLayout(boolean, int, int, int, int) (FrameLayout.java:270)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.View.layout(int, int, int, int) (View.java:22160)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6402)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.widget.LinearLayout.setChildFrame(android.view.View, int, int, int, int) (LinearLayout.java:1829)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.widget.FrameLayout.layoutChildren(int, int, int, int, boolean) 03-13 12:05:07.876 F/w_stackoverflo(12828): java_vm_ext.cc:570]   at void android.widget.LinearLayout.layoutVertical(int, int, int, int) (LinearLayout.java:1673)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.View.layout(int, int, int, int) (View.java:22160)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.Vi03-13 12:05:07.876 F/w_stackoverflo(12828): java_vm_ext.cc:570]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6402)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.widget.FrameLayout.layoutChildren(int, int, int, int, boolean) (FrameLayout.java:332)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.widget.FrameLayout.onLayout(boolean, int, int, int, int) (FrameLayout.java:270)
[w_stackoverflo] java_vm_ext.cc:570]   at void com.android.internal.policy.DecorView.onLayout(boolean, int, int, int, int) (DecorView.java:810)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.ViewGroup.layout(int, int, int, int) (ViewGroup.java:6402)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.ViewRootImpl.performLayout(android.view.WindowManager$LayoutParams, int, int) (ViewRootImpl.java:3330)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.ViewRootImpl.performTraversals() (ViewRootImpl.java:2826)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.03-13 12:05:07.876 F/w_stackoverflo(12828): java_vm_ext.cc:570]   at void android.view.ViewRootImpl.doTraversal() (ViewRootImpl.java:1901)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.ViewRootImpl$TraversalRunnable.run() (ViewRootImpl.java:8066)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.Choreographer$CallbackRecord.run(long) (Choreographer.java:1041)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.Choreographer.doCallbacks(int, long) (Choreographer.java:860)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.Choreographer.doFrame(long, int) (Choreographer.java:785)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.view.Choreographer$FrameDisplayEventReceiver.run() (Choreographer.java:1026)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.os.Handler.handleCallback(android.os.Message) (Handler.java:914)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:100)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.os.Looper.loop() (Looper.java:225)
[w_stackoverflo] java_vm_ext.cc:570]   at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:7563)
[w_stackoverflo] java_vm_ext.cc:570]   at void com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run() (RuntimeInit.java:539)
[w_stackoverflo] java_vm_ext.cc:570]   at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:994)
[w_stackoverflo] java_vm_ext.cc:570] 
[w_stackoverflo] java_vm_ext.cc:570]     in call to GetObjectClass
[w_stackoverflo] java_vm_ext.cc:570]     from void crc6414252951f3f66c67.CarouselViewAdapter_2.n_onBindViewHolder(androidx.recyclerview.widget.RecyclerView$ViewHolder, int)

I have tried to catch the error by debugging both Xamarin.CommunityToolkit and your CarouselView library, but I was only getting a crash without having being able to get a hint...

Also, I can see a related issue #560 which seems to be fixed in 6.0.0. Then I may think that your fix works if the content is loaded in a ContentPage, but maybe not in a ContentView ?

Steps to Reproduce

  1. Run the repo on Android
  2. Clicks on the third tab where it says "ScrollView + Carousel"
  3. You can see the app is crashing and gives a StackOverflowError in Application Output

Basic Information

  • Version with issue: 6.0.0
  • Last known good version: N/A
  • IDE: VS for Mac v8.9.1
  • Platform Target Frameworks:
    • iOS: 14.4
    • Android: 11.0 (R)
  • Nuget Packages:
    • Xamarin.Forms 5.0.0.2012,
    • Xamarin.Essentials 1.6.1,
    • Xamarin.CommunityToolkit 1.1.0-pre2
  • Affected Devices: Redmi 9A, Android 10 (Q)

Workaround

  1. Replacing ScrollView with a grid works fine, but I really need the ScrollView in my page.
  2. Load the tab content in a new page, but I lose the benefit of using bottom tabs.

Reproduction Link

CarouselView_Stackoverflow.zip

Kapusch avatar Mar 13 '21 11:03 Kapusch

Maybe it's related to this https://github.com/xamarin/XamarinCommunityToolkit/issues/1104 ?

Kapusch avatar Apr 02 '21 21:04 Kapusch

Hi, I actually got the issue from an endless recursive loop in the CarouselViewImplementation.

Indeed, the method Android.App.Activity FindActivity(Context context) is continuously called itself here:

var contextThemeWrapper = _context as Android.Views.ContextThemeWrapper;
if (contextThemeWrapper != null)
{
    return FindActivity(contextThemeWrapper.BaseContext);
}

as it is not able to find the MainActivity :/

Do you think you could have a look at it please @alexrainman ?

Kapusch avatar Apr 05 '21 09:04 Kapusch

Here are some logs in case that helps a little bit:

Console logs for a working Carousel controller
-------> Call of FindActivity from CarouselViewRenderer
-------> FindActivity called 1 times
-------> Rercursive call of FindActivity 
-------> FindActivity called 2 times

-------> Call of FindActivity from SetNativeView
-------> FindActivity called 3 times
-------> Rercursive call of FindActivity 
-------> FindActivity called 4 times
Console logs for crashing Carousel controller
-------> Call of FindActivity from CarouselViewRenderer
-------> FindActivity called 1 times
-------> Rercursive call of FindActivity 
-------> FindActivity called 2 times
-------> Rercursive call of FindActivity 
-------> FindActivity called 3 times
-------> Rercursive call of FindActivity 
-------> FindActivity called 4 times
.......
-------> Rercursive call of FindActivity 
-------> FindActivity called a billion times

Kapusch avatar Apr 05 '21 09:04 Kapusch

Actually @alexrainman , I think it is because the same object is passed through the recursive call.

Indeed, _context.BaseContext is always passed, so if MainActivity is not found during the first recursive call, then it will trigger an endless loop.

Kapusch avatar Apr 05 '21 09:04 Kapusch

Hello @alexrainman , sorry to spam you, but I think I have fixed my issue by replacing https://github.com/alexrainman/CarouselView/blob/eda4fd3757297a619aef4518af2a1da441402440/CarouselView/CarouselView.FormsPlugin.Android/CarouselViewImplementation.cs#L82

with

var contextThemeWrapper = context as Android.Views.ContextThemeWrapper;

But I'm only able to validate the fix by running your demo project... Actually, I'm not sure if the new NuGet I have generated is valid :/

Could you please help me to understand how to directly refer your source code into my repro project ?

Kapusch avatar Apr 06 '21 20:04 Kapusch

Isn't var contextThemeWrapper = _context as Android.Views.ContextThemeWrapper; the same as var contextThemeWrapper = context as Android.Views.ContextThemeWrapper;?

alexrainman avatar Jun 22 '21 20:06 alexrainman