InsertKoinIO / koin

Koin - a pragmatic lightweight dependency injection framework for Kotlin & Kotlin Multiplatform
https://insert-koin.io
Apache License 2.0
8.98k stars 710 forks source link

The method with @composeable annotations is defined in the interface to get exceptions #1757

Closed CYF-66 closed 7 months ago

CYF-66 commented 8 months ago

Hey guys I have a issue and would like your help, thank you

When defining a method with @composeable annotations in the interface, the object is obtained by inject() or get(), but the method with the @composeable annotation cannot be found when used

Step 1

interface A {

    @Composable
    fun B()

    fun C()
}

Step 2

class AImpl : A {

    @Composable
    override fun B() {
        println("AImpl.B")
    }

   override fun C() {
        println("AImpl.C")
    }
}

Step 3

val moduleA = module {

    factory<A> {
        AImpl()
    }
}

Step 4

class MainApplication : Application() {

    override fun onCreate() {
        startKoin {
            androidLogger(Level.NONE)
            androidContext(this@MainApplication)
            modules(
                moduleA
            )
        }
    }
}

Step 5

class TestActivity : AppCompatActivity() {

    private val a: A by inject()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            GrpcDemoTheme {
                a.C()
                a.B() 
            }
        }
    }
}

a.C() work fine , a.B() will crash The following error is reported:

FATAL EXCEPTION: main Process: com.freddy.sample, PID: 26329 java.lang.NoSuchMethodError: No interface method B(Landroidx/compose/runtime/Composer;I)V in class Lcom/freddy/sample/A; or its super classes (declaration of 'com.freddy.sample.A' appears in /data/data/com.freddy.sample/code_cache/.overlay/base.apk/classes8.dex)

Step 6

Change the method of obtaining an object from by inject() to direct instantiation of AImpl(), and the code is as follows

class TestActivity : AppCompatActivity() {

    // private val a: A by inject()
    private val a = AImpl()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            GrpcDemoTheme {
                a.C()
                a.B() 
            }
        }
    }
}

a.C() work fine , a.B() work fine Everything was fine

Question

This can be seen by comparing steps 5 and 6 , Is it that when an interface defines a method with a @composeable annotation, you can't get the method by inject() or get(). , If you initialize the AImpl() instance directly, everything was fine

koinVersion = "3.1.2"

arnaudgiuliani commented 8 months ago

any relation with Koin?

CYF-66 commented 8 months ago

If you initialize the AImpl() instance directly, do the same in step 5 below a.C() a.B() Everything was fine. There were no errors, Do you know why? @arnaudgiuliani Step 5

.......

private val a: A by inject()

change to

private val a = AImpl()

...... setContent { GrpcDemoTheme { a.C() a.B() } }

arnaudgiuliani commented 8 months ago

I would say it's about Compose here, but not sure to understand well. Please use the "code block" to help us read :)

CYF-66 commented 8 months ago

I've described the whole process in detail here, so you can take a look @arnaudgiuliani

arnaudgiuliani commented 7 months ago

can you try without Koin, to declare those Composables?

CYF-66 commented 7 months ago

Yes, The Step 6 is to use the instance without using koin to declare that it can be used normally @arnaudgiuliani