Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash when Android-specific classes are used as top-level val #27

Open
mxalbert1996 opened this issue Sep 17, 2024 · 3 comments
Open

Crash when Android-specific classes are used as top-level val #27

mxalbert1996 opened this issue Sep 17, 2024 · 3 comments

Comments

@mxalbert1996
Copy link

We are trying to use ComposablePreviewScanner with Paparazzi.
We have some components that use Android-specific classes in it, and the scanner crashes when scanning these classes.

Example 1

private val SomePath = android.graphics.Path().apply { ... }

The scanner crashes with

java.lang.UnsatisfiedLinkError: 'long android.graphics.Path.nInit()'
	at android.graphics.Path.nInit(Native Method)
	at android.graphics.Path.<init>(Path.java:51)
	at mypackage.SomeComponentKt.<clinit>

Example 2

private val Typeface = android.graphics.Typeface.create("sans-serif-medium", Typeface.NORMAL)

The scanner crashes with

java.lang.NullPointerException: Cannot invoke "java.util.Map.get(Object)" because "android.graphics.Typeface.sSystemFontMap" is null
	at android.graphics.Typeface.getSystemDefaultTypeface(Typeface.java:1216)
	at android.graphics.Typeface.create_Original(Typeface.java:899)
	at android.graphics.Typeface_Delegate.create(Typeface_Delegate.java:109)
	at android.graphics.Typeface.create(Typeface.java:899)
	at mypackage.SomeComponentKt.<clinit>

After Paparazzi is initialized (when using Paparazzi as the test rule), the crash doesn't happen, but the preview list need to be generated before the test rule kicks in.

We can use something like lazy as a workaround, but I'm wondering if there's some other way that doesn't require code change.

@mxalbert1996 mxalbert1996 changed the title Crash when Android-specific classes are used Crash when Android-specific classes are used as top-level val Sep 17, 2024
@sergio-sastre
Copy link
Owner

sergio-sastre commented Sep 17, 2024

@mxalbert1996
So I can reproduce it, and this happens only with Paparazzi: with Roborazzi this is not reproducible. I think the best to avoid this is to use some lazy initialization as you mentioned, or just make those vals compute those values every time

private val SomePath 
   get() = android.graphics.Path()

instead of this

private val SomePath = android.graphics.Path()

Another option would be to put your @Previews inside a class, which is supported since ComposablePreviewScanner 0.3.0.

Just let me know if it helps

@sergio-sastre
Copy link
Owner

sergio-sastre commented Sep 17, 2024

I believe it might work without changing those global vals if you use ParameterizedRunner instead of the TestParameterInjector.

How to set it up is explained in the Roborazzi section. The setup the same, but use ParameterizedTestRunner instead of RobolectricParameterizedTest.

So only the test code would need changes

I’ll give it a try tonight and report back

@sergio-sastre
Copy link
Owner

I believe it might work without changing those global vals if you use ParameterizedRunner instead of the TestParameterInjector.

How to set it up is explained in the Roborazzi section. The setup the same, but use ParameterizedTestRunner instead of RobolectricParameterizedTest.

So only the test code would need changes

I’ll give it a try tonight and report back

Looks like using Parameterized instead of TestParameterInjector makes no difference.
The issue seems to be related to the way Paparazzi download android resources, which seems to interfere somehow with ComposablePreviewScanner, so my best bet is that you'll have to resort to one of the approaches I mentioned previously

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants