adrielcafe / voyager

🛸 A pragmatic navigation library for Jetpack Compose
https://voyager.adriel.cafe
MIT License
2.42k stars 117 forks source link

getScreenModel returns "... not found in hilt graph" #148

Closed ydhnwb closed 10 months ago

ydhnwb commented 1 year ago

I have a simple module like this:

@Module
@InstallIn(SingletonComponent::class)
class NoteDataSource {

    @Provides
    @Singleton
    fun getAllNotes() : List<String> {
        val notes = (0..25).map { "Notes from data #$it | ${UUID.randomUUID().toString().substringBefore('-')}" }
        return notes
    }
}

And NoteDataSource will be injected to ListScreenModel like this:

class ListScreenModel @Inject constructor(
    private val noteDataSource: NoteDataSource
) : ScreenModel {

    fun getItems2() : List<String> {
        return noteDataSource.getAllNotes()
    }
    override fun onDispose() {
        super.onDispose()
    }

Using it inside AndroidScreen() via getScreenModel like this:

class ListNotesScreen: AndroidScreen() {
    override val key: ScreenKey = uniqueScreenKey

    @OptIn(ExperimentalMaterial3Api::class)
    @Composable
    override fun Content() {
        val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState())
        val navigator = LocalNavigator.currentOrThrow
        val screenModel = getScreenModel<ListScreenModel>()
        ....

But it returns error like:

 java.lang.IllegalStateException: class com.ydhnwb.myapplication.feature.list_note.ListScreenModel not found in hilt graph.

 Please, check if you have a Multibinding declaration to your ScreenModel using @IntoMap and @ScreenModelKey(com.ydhnwb.myapplication.feature.list_note.ListScreenModel::class)

I already added @HiltAndroidApp and @AndroidEntryPoint. Am I missing something or this is a bug?

AntsyLich commented 1 year ago

You need to manually add the model to hilt graph like below

@Module
@InstallIn(ActivityComponent::class)
@Suppress("UNUSED")
abstract class ListScreenModule {
    @Binds
    @IntoMap
    @ScreenModelKey(ListScreenModel::class)
    abstract fun ListScreenModel.binds(): ScreenModel
}