androidx.compose.ui.graphics.Color causing error during reflection
Open
viratshukla
opened this issue 4 years ago
•
15 comments
Hi,
I am using reflection to invoke a composable method in some file. If that file has any method, which takes androidx.compose.ui.graphics.Color as a parameter, reflection fails.
Please find complete stack trace for the same.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.composeplayground, PID: 30706
kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Inconsistent number of parameters in the descriptor and Java reflection object: 3 != 1
Calling: public fun Widget2(a: androidx.compose.ui.graphics.Color): kotlin.Unit defined in com.example.composeplayground.dsLibrary[DeserializedSimpleFunctionDescriptor@ec84127]
Parameter types: [long, interface androidx.compose.runtime.Composer, int])
Default: false
at kotlin.reflect.jvm.internal.calls.InlineClassAwareCaller.(InlineClassAwareCaller.kt:102)
at kotlin.reflect.jvm.internal.calls.InlineClassAwareCallerKt.createInlineClassAwareCallerIfNeeded(InlineClassAwareCaller.kt:159)
at kotlin.reflect.jvm.internal.calls.InlineClassAwareCallerKt.createInlineClassAwareCallerIfNeeded$default(InlineClassAwareCaller.kt:149)
at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:89)
at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:61)
at kotlin.reflect.jvm.internal.ReflectProperties$LazyVal.invoke(ReflectProperties.java:63)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
at kotlin.reflect.jvm.internal.KFunctionImpl.getCaller(KFunctionImpl.kt:61)
at kotlin.reflect.jvm.ReflectJvmMapping.getJavaMethod(ReflectJvmMapping.kt:63)
at kotlin.reflect.jvm.ReflectJvmMapping.getKotlinFunction(ReflectJvmMapping.kt:122)
at com.example.composeplayground.MainActivityKt.UseReflection(MainActivity.kt:50)
at com.example.composeplayground.ComposableSingletons$MainActivityKt$lambda-1$1.invoke(MainActivity.kt:35)
at com.example.composeplayground.ComposableSingletons$MainActivityKt$lambda-1$1.invoke(MainActivity.kt:34)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.material.SurfaceKt$Surface$6.invoke(Surface.kt:267)
at androidx.compose.material.SurfaceKt$Surface$6.invoke(Surface.kt:254)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215)
at androidx.compose.material.SurfaceKt.Surface-F-jzlyU(Surface.kt:251)
at androidx.compose.material.SurfaceKt.Surface-F-jzlyU(Surface.kt:110)
at com.example.composeplayground.ComposableSingletons$MainActivityKt$lambda-2$1.invoke(MainActivity.kt:34)
at com.example.composeplayground.ComposableSingletons$MainActivityKt$lambda-2$1.invoke(MainActivity.kt:32)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215)
at androidx.compose.material.TextKt.ProvideTextStyle(Text.kt:252)
at androidx.compose.material.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:81)
at androidx.compose.material.MaterialThemeKt$MaterialTheme$1.invoke(MaterialTheme.kt:80)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215)
at androidx.compose.material.MaterialThemeKt.MaterialTheme(MaterialTheme.kt:72)
at com.example.composeplayground.ui.theme.ThemeKt.ComposePlaygroundTheme(Theme.kt:41)
at com.example.composeplayground.ComposableSingletons$MainActivityKt$lambda-3$1.invoke(MainActivity.kt:32)
at com.example.composeplayground.ComposableSingletons$MainActivityKt$lambda-3$1.invoke(MainActivity.kt:31)
E/AndroidRuntime: at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.ui.platform.ComposeView.Content(ComposeView.android.kt:384)
at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:228)
at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:227)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215)
at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:148)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:114)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:113)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:106)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:162)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:161)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:161)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:144)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.ComposerKt.invokeComposable(Composer.kt:3330)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2577)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2573)
at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(SnapshotState.kt:540)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:2566)
at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:2517)
at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:476)
at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:727)
at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:432)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:144)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:135)
at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:727)
at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:135)
at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:187)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:354)
at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:196)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:142)
E/AndroidRuntime: at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:135)
at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:814)
at android.view.View.dispatchAttachedToWindow(View.java:18347)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3397)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3404)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3404)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3404)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3404)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1761)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1460)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7183)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
at android.view.Choreographer.doCallbacks(Choreographer.java:761)
at android.view.Choreographer.doFrame(Choreographer.java:696)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
I/Process: Sending signal. PID: 30706 SIG: 9
@Composable
fun UseReflection() {
val packageName = "com.example.composeplayground.dsLibrary.MyComposeWidgets"
val functionName = "Widget1"
val c = Class.forName("${packageName}Kt")
c.declaredMethods.forEach { method ->
if (method.kotlinFunction?.name == functionName) {
InvokeMethod(method)
}
}
}
@Composable
fun InvokeMethod(method : Method) {
val dataToBeInvoked = arrayListOf<Any?>()
method.kotlinFunction?.parameters?.forEachIndexed { index, param ->
dataToBeInvoked.add(paramList1[index])
}
// Since compiler adds currentCompose in signature
dataToBeInvoked.add(currentComposer)
// Some random zeroes are also added during compile time, hence this logic
val javaParamCount = method.parameterCount
val numOfZeroesToBeAdded = javaParamCount - dataToBeInvoked.size
for (x in 1..numOfZeroesToBeAdded) {
dataToBeInvoked.add(0)
}
method.kotlinFunction?.call(*dataToBeInvoked.toTypedArray())
@akurasov I need to generate some generic code, so that on runtime, I can show correct UI based on response.
Yes, I am aware, that on compile time, currentComposer and some integers are added.
And this reflection is working fine in all the cases, except this Color param or Dp param in method signature.
Can you please let me know the solution, if possible?
// Some random zeroes are also added during compile time, hence this logic
This is just not deterministic, since Compose compiler does not make any guarantees how many additional parameters it's adding to composable functions, where it's adding them, what is the type, and most importantly, what the values should be. So randomly adding zeroes as integers is inviting a really big trouble to begin with.
This is not a desktop-specific issue. I'd recommend either revisiting the approach to not use reflection at all, or to open a discussion on the Compose main tracker / #compose channel in Kotlin discord.
@akurasov
Hi,
Basically, I have created all my Composable components and I am writing a wrapper using reflection, which will decide in run-time, which component should be displayed.