JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
16.15k stars 1.17k forks source link

java.lang.NoSuchMethodError: No static method drawText #2673

Closed wakaztahir closed 1 year ago

wakaztahir commented 1 year ago

I've seen a lot of errors recently of this type

What I want to do is create a multiplatform module that I consume inside my android module , where the multiplatform module uses Jetbrains compose-b and android module uses the jetpack compose from google

Compatibility Issue Between Google's Jetpack Compose & JetBrains Compose-JB

Here's my configuration , Please let me know how can I ensure that the compatibility between Google's Jetpack Compose & Jetbrains Compose-JB doesn't break , I would love to change my configuration to fix these type of errors but at the same time I expect a solution that I can follow in the future to never come across problem in compatibility issues.

kotlin_version=1.8.0
agp_version=7.4.0
compose_version=1.3.0
compose_compiler_version=1.4.0
compose.jb.version=1.3.0-rc05
java.lang.NoSuchMethodError: No static method drawText-xIhfjkU$default(Landroidx/compose/ui/graphics/drawscope/DrawScope;Landroidx/compose/ui/text/TextLayoutResult;JJFLandroidx/compose/ui/graphics/Shadow;Landroidx/compose/ui/text/style/TextDecoration;ILjava/lang/Object;)V in class Landroidx/compose/ui/text/TextPainterKt; or its super classes (declaration of 'androidx.compose.ui.text.TextPainterKt' appears in /data/app/~~mhcP0EP9NVOo9AsAxvneWQ==/com.wakaztahir.sketchapp-uSAeUO4aP9HLa2VbCVcCqw==/base.apk)
                                                                                                        at com.wakaztahir.sketchable.layers.TextLayer.draw(TextLayer.kt:144)
                                                                                                        at com.wakaztahir.sketchable.canvas.DrawSketchKt.drawSketch(drawSketch.kt:15)
                                                                                                        at com.wakaztahir.sketchapp.activities.EditorActivity$onCreate$1$1$1$1$1$3$1$1$1.invoke(EditorActivity.kt:175)
                                                                                                        at com.wakaztahir.sketchapp.activities.EditorActivity$onCreate$1$1$1$1$1$3$1$1$1.invoke(EditorActivity.kt:170)
                                                                                                        at androidx.compose.ui.draw.DrawBackgroundModifier.draw(DrawModifier.kt:113)
                                                                                                        at androidx.compose.ui.node.LayoutNodeDrawScope.draw-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:92)
                                                                                                        at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:368)
                                                                                                        at androidx.compose.ui.node.NodeCoordinator.access$drawContainedDrawModifiers(NodeCoordinator.kt:58)
                                                                                                        at androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke(NodeCoordinator.kt:394)
                                                                                                        at androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke(NodeCoordinator.kt:393)
                                                                                                        at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2139)
                                                                                                        at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:234)
                                                                                                        at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:230)
                                                                                                        at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341)
                                                                                                        at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1)
                                                                                                        at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:230)
                                                                                                        at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:120)
                                                                                                        at androidx.compose.ui.node.NodeCoordinator.invoke(NodeCoordinator.kt:393)
                                                                                                        at androidx.compose.ui.node.NodeCoordinator.invoke(NodeCoordinator.kt:58)
                                                                                                        at androidx.compose.ui.platform.RenderNodeApi29.record(RenderNodeApi29.android.kt:209)
                                                                                                        at androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList(RenderNodeLayer.android.kt:301)
                                                                                                        at androidx.compose.ui.platform.AndroidComposeView.dispatchDraw(AndroidComposeView.android.kt:1019)
                                                                                                        at android.view.View.draw(View.java:23005)
                                                                                                        at android.view.View.updateDisplayListIfDirty(View.java:21869)
                                                                                                        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4526)
                                                                                                        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4499)
                                                                                                        at android.view.View.updateDisplayListIfDirty(View.java:21820)
                                                                                                        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4526)
                                                                                                        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4499)
                                                                                                        at android.view.View.updateDisplayListIfDirty(View.java:21820)
                                                                                                        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4526)
                                                                                                        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4499)
                                                                                                        at android.view.View.updateDisplayListIfDirty(View.java:21820)
                                                                                                        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4526)
                                                                                                        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4499)
                                                                                                        at android.view.View.updateDisplayListIfDirty(View.java:21820)
                                                                                                        at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:534)
                                                                                                        at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:542)
                                                                                                        at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:625)
                                                                                                        at android.view.ViewRootImpl.draw(ViewRootImpl.java:4652)
                                                                                                        at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4370)
2023-01-27 13:54:12.874 18458-18458 AndroidRuntime          com.wakaztahir.sketchapp             E      at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3481)
                                                                                                        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2272)
                                                                                                        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8999)
                                                                                                        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1160)
                                                                                                        at android.view.Choreographer.doCallbacks(Choreographer.java:950)
                                                                                                        at android.view.Choreographer.doFrame(Choreographer.java:879)
                                                                                                        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1142)
                                                                                                        at android.os.Handler.handleCallback(Handler.java:938)
                                                                                                        at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                                                        at android.os.Looper.loopOnce(Looper.java:210)
                                                                                                        at android.os.Looper.loop(Looper.java:299)
                                                                                                        at android.app.ActivityThread.main(ActivityThread.java:8309)
                                                                                                        at java.lang.reflect.Method.invoke(Native Method)
                                                                                                        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556)
                                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1038)
dima-avdeev-jb commented 1 year ago

Can you please share a reproducible sample on GitHub?

wakaztahir commented 1 year ago

Here's a reproducer

https://github.com/wakaztahir/no-static-method-error-in-compose

I also would like you to know that this error doesn't just occur here , It occurs sometimes with other methods like my own methods , for example the Theme function or other methods start failing because they are in library , annoying error !

dima-avdeev-jb commented 1 year ago

I found a problem and fixed it in PR https://github.com/wakaztahir/no-static-method-error-in-compose/pull/1

This kind of error appears if the function signature inside Compose-multiplatform and Android JetPack Compose differs. In this case, you use an experimental function, which means the signature may break.

@ExperimentalTextApi
fun DrawScope.drawText(

When we are building Compose-multiplatform we target's to some version of Compose libraries available at the current moment. And if it's experimental. You are using an alpha version of material3 "androidx.compose.material3:material3:1.1.0-alpha05" and it differs with a Compose-multiplatform version. Because of alpha status, backward compatibility was changed. But, you can use the same version as in common module. implementation(compose.material3) This version is also experimental, but will have the same signature on Android and Common sourceset.

If you are doing libraries based on experimental versions of another library, it's a big risk to break backward compatibility between your library and other libraries. So, please add alpha suffix to library versions what you doing.

This kind of errors is hard to debug. And it may cause a lot of problems if your application is not having UI tests.

So, the recommendations:

wakaztahir commented 1 year ago

Thanks for the effort

okushnikov commented 3 months ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.