#android #kotlin #android-jetpack-compose #kotlin-multiplatform #compose-desktop
Вопрос:
Я разрабатываю фиктивное приложение для погоды с помощью мультиплатформенной платформы Kotlin. Я использую Decompose и MVIKotlin, чтобы попытаться поделиться всей бизнес-логикой, кроме собственных пользовательских интерфейсов, SwiftUI для IOS и Compose для настольных компьютеров и Android.
Я пытаюсь создать ожидаемую композицию (для темной темы и для загрузки изображений).
// In common main
@Composable
expect fun isDarkMode() : Boolean
@Composable
expect fun loadWeatherIcon(id : Int) : Painter
// In android main
@Composable
actual fun isDarkMode() : Boolean {
return androidx.compose.foundation.isSystemInDarkTheme()
}
@Composable
actual fun loadWeatherIcon(id : Int) : Painter {
return painterResource(id)
}
//In Desktop main
@Composable
actual fun isDarkMode() : Boolean {
return false //isSystemInDarkTheme()
}
@Composable
actual fun loadWeatherIcon(id : Int) : Painter {
return loadWeatherIcon(id)
}
Это означает, что все они реализованы и есть, но по какой-то причине сбой происходит с ошибкой noSuchMethod. Я обнаружил некоторые похожие проблемы, но все они имели функции приостановки и параметры по умолчанию. Между тем мой подход должен работать, как в примере jetpack todo compose, вот мой проект (если вы хотите проверить, что происходит, вы можете просто клонировать его и запустить, он должен немедленно рухнуть).
https://github.com/Nikola-Milovic/KotlinMultiplaftorm-WeatherApp
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.nikolam.kmm_weather.androidApp, PID: 17270
java.lang.NoSuchMethodError: No static method isDarkMode(Landroidx/compose/runtime/Composer;I)Z in class Lcom/nikolam/kmm_weather/ui/UtilsKt; or its super classes (declaration of 'com.nikolam.kmm_weather.ui.UtilsKt' appears in /data/data/com.nikolam.kmm_weather.androidApp/code_cache/.overlay/base.apk/classes4.dex)
at com.nikolam.kmm_weather.ui.WeatherMainContentKt$WeatherMainContent$2.invoke(WeatherMainContent.kt:45)
at com.nikolam.kmm_weather.ui.WeatherMainContentKt$WeatherMainContent$2.invoke(WeatherMainContent.kt:38)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:193)
at com.nikolam.kmm_weather.ui.WeatherMainContentKt.WeatherMainContent(WeatherMainContent.kt:38)
at com.nikolam.kmm_weather.ui.ComposableSingletons$WeatherRootContentKt$lambda-1$1.invoke(WeatherRootContent.kt:14)
at com.nikolam.kmm_weather.ui.ComposableSingletons$WeatherRootContentKt$lambda-1$1.invoke(WeatherRootContent.kt:12)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:118)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at com.arkivanov.decompose.extensions.compose.jetbrains.ChildrenKt$Children$1$1.invoke(Children.kt:30)
at com.arkivanov.decompose.extensions.compose.jetbrains.ChildrenKt$Children$1$1.invoke(Children.kt:29)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:193)
at androidx.compose.runtime.saveable.SaveableStateHolderImpl.SaveableStateProvider(SaveableStateHolder.kt:84)
at com.arkivanov.decompose.extensions.compose.jetbrains.ChildrenKt$Children$1.invoke(Children.kt:29)
at com.arkivanov.decompose.extensions.compose.jetbrains.ChildrenKt$Children$1.invoke(Children.kt:28)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:118)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at com.arkivanov.decompose.extensions.compose.jetbrains.animation.page.PageAnimationKt$PageAnimationFrame$1$1$1.invoke(PageAnimation.kt:143)
at com.arkivanov.decompose.extensions.compose.jetbrains.animation.page.PageAnimationKt$PageAnimationFrame$1$1$1.invoke(PageAnimation.kt:141)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:118)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at com.arkivanov.decompose.extensions.compose.jetbrains.animation.child.CrossfadeScaleKt$crossfadeScale$1.invoke(CrossfadeScale.kt:22)
at com.arkivanov.decompose.extensions.compose.jetbrains.animation.child.CrossfadeScaleKt$crossfadeScale$1.invoke(CrossfadeScale.kt:21)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:254)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at com.arkivanov.decompose.extensions.compose.jetbrains.animation.page.PageAnimationKt$PageAnimationFrame$1.invoke(PageAnimation.kt:141)
at com.arkivanov.decompose.extensions.compose.jetbrains.animation.page.PageAnimationKt$PageAnimationFrame$1.invoke(PageAnimation.kt:132)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:118)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1$measurables$1.invoke(BoxWithConstraints.kt:61)
E/AndroidRuntime: at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1$measurables$1.invoke(BoxWithConstraints.kt:61)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2$1.invoke(SubcomposeLayout.kt:167)
at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2$1.invoke(SubcomposeLayout.kt:167)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.ComposerKt.invokeComposable(Composer.kt:3235)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:2514)
at androidx.compose.runtime.ComposerImpl.composeContent$runtime_debug(Composer.kt:2478)
at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:453)
at androidx.compose.runtime.Recomposer.composeInitial$runtime_debug(Recomposer.kt:702)
at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_debug(Composer.kt:2914)
at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:409)
at androidx.compose.ui.layout.SubcomposeLayoutState.subcomposeInto(SubcomposeLayout.kt:184)
at androidx.compose.ui.layout.SubcomposeLayoutState.access$subcomposeInto(SubcomposeLayout.kt:100)
at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2.invoke(SubcomposeLayout.kt:160)
at androidx.compose.ui.layout.SubcomposeLayoutState$subcompose$2.invoke(SubcomposeLayout.kt:158)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.withNoObservations(SnapshotStateObserver.kt:137)
at androidx.compose.ui.node.OwnerSnapshotObserver.withNoSnapshotReadObservation$ui_debug(OwnerSnapshotObserver.kt:49)
at androidx.compose.ui.node.LayoutNode.withNoSnapshotReadObservation$ui_debug(LayoutNode.kt:1054)
at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose(SubcomposeLayout.kt:158)
at androidx.compose.ui.layout.SubcomposeLayoutState.subcompose(SubcomposeLayout.kt:152)
at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1.invoke-0kLqBqw(BoxWithConstraints.kt:61)
at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1.invoke(BoxWithConstraints.kt:59)
at androidx.compose.ui.layout.SubcomposeLayoutState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:212)
at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:45)
at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:95)
at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:94)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:121)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_debug(OwnerSnapshotObserver.kt:75)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_debug(OwnerSnapshotObserver.kt:63)
at androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(OuterMeasurablePlaceable.kt:94)
at androidx.compose.ui.node.OuterMeasurablePlaceable.measure-BRTryo0(OuterMeasurablePlaceable.kt:68)
at androidx.compose.ui.node.LayoutNode.measure-BRTryo0(LayoutNode.kt:1172)
at androidx.compose.foundation.layout.BoxKt$boxMeasurePolicy$1.measure-3p2s80s(Box.kt:111)
at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:45)
at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:213)
at androidx.compose.ui.node.ModifiedLayoutNode.measure-BRTryo0(ModifiedLayoutNode.kt:37)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108)
E/AndroidRuntime: at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:213)
at androidx.compose.ui.node.ModifiedLayoutNode.measure-BRTryo0(ModifiedLayoutNode.kt:37)
at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:95)
at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:94)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:121)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_debug(OwnerSnapshotObserver.kt:75)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_debug(OwnerSnapshotObserver.kt:63)
at androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(OuterMeasurablePlaceable.kt:94)
at androidx.compose.ui.node.OuterMeasurablePlaceable.measure-BRTryo0(OuterMeasurablePlaceable.kt:68)
at androidx.compose.ui.node.LayoutNode.measure-BRTryo0(LayoutNode.kt:1172)
at androidx.compose.ui.layout.RootMeasurePolicy.measure-3p2s80s(RootMeasurePolicy.kt:38)
at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:45)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:108)
at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:95)
at androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke(OuterMeasurablePlaceable.kt:94)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:1787)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:116)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_debug(OwnerSnapshotObserver.kt:75)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_debug(OwnerSnapshotObserver.kt:63)
at androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(OuterMeasurablePlaceable.kt:94)
at androidx.compose.ui.node.LayoutNode.remeasure-BRTryo0$ui_debug(LayoutNode.kt:1179)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-0kLqBqw(MeasureAndLayoutDelegate.kt:170)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.access$doRemeasure-0kLqBqw(MeasureAndLayoutDelegate.kt:39)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:212)
at androidx.compose.ui.platform.AndroidComposeView.onMeasure(AndroidComposeView.android.kt:543)
at android.view.View.measure(View.java:25466)
at androidx.compose.ui.platform.AbstractComposeView.onMeasure(ComposeView.android.kt:249)
at android.view.View.measure(View.java:25466)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:145)
at android.view.View.measure(View.java:25466)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
at android.view.View.measure(View.java:25466)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at android.view.View.measure(View.java:25466)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
E/AndroidRuntime: at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
at android.view.View.measure(View.java:25466)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at com.android.internal.policy.DecorView.onMeasure(DecorView.java:747)
at android.view.View.measure(View.java:25466)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:3397)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:2228)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2486)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1952)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8171)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
at android.view.Choreographer.doCallbacks(Choreographer.java:796)
at android.view.Choreographer.doFrame(Choreographer.java:731)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
I/Process: Sending signal. PID: 17270 SIG:
Ответ №1:
Я столкнулся с аналогичной проблемой, когда @Composable
аннотированная ожидаемая функция не была видна во время выполнения в другом модуле Gradle. Отсюда java.lang.NoSuchMethodError
и исключение. Решение состояло в том, чтобы сделать ожидаемую функцию внутренней и делегировать этой внутренней функции общедоступную функцию-оболочку.
Сбои:
@Composable
expect fun Image() { ... }
Не разбивается:
@Composable
internal expect fun InternalImage() { ... }
@Composable
fun Image() {
InternalImage()
}