https://kotlinlang.org logo
#dagger
Title
# dagger
b

blakelee

12/06/2021, 8:01 PM
Is it possible to have fragment scoped custom providers for viewmodels? Here is what I currently have to do: • I create my custom object
Copy code
@Module
@InstallIn(FragmentComponent::class)
object FragmentModule {
    @Provides
    @FragmentScoped
    fun provideMyObject(fragment: Fragment): MyObject {
        return fragment.getMyObject() // I can only get this from a fragment
    }
}
• I create my ViewModel without
@HiltViewModel
but with
@Inject constructor
• In my fragment I inject it with assisted inject
Copy code
@Inject
lateinit var provider: Provider<MyViewModel>

private val viewModel: MyViewModel by assistedViewModel { provider.get() }
Since I know I'm only going to be using this ViewModel in a fragment, it would be nice to be able to get items from a fragment.
a

alex.krupa

12/14/2021, 12:08 PM
You're trying to inject
MyObject
obtained from a fragment directly into a view model – did I understand it correctly? E.g.
Copy code
class MyViewModel(
    private val myObject: MyObject
)
b

blakelee

12/15/2021, 10:40 PM
Yes, that is correct. I am getting the VM inside of a fragment by using
val viewModel: MyViewModel = viewModels()
. So in my ViewModel I want to be able to inject an item that is scoped to that fragment. I am trying to avoid using the savedStateHandle -- Or maybe I can even set the item in the savedStateHandle, then create a ViewModelComponent that extracts the item from it
a

alex.krupa

12/16/2021, 4:22 PM
SavedStateHandle
is indeed one approach AFAIK (haven't used it myself). The other one I know is using assisted injection – which you mentioned, but aren't actually using, because that requires
@AssistedInject
,
@Assisted
and
@AssistedFactory
annotations. Here's an example.
Copy code
class MyViewModel @AssistedInject constructor(
    private val regularObject: RegularObject, // Non-assisted dependency
    @Assisted private val myObject: MyObject, // Assisted dependency
) {

    @AssistedFactory
    interface Factory {

        // Only assisted dependencies in this signature.
        fun create(myObject: MyObject): MyViewModel
    }
}

class MyFragment : Fragment() {
    
    @Inject lateinit var viewModelFactory: MyViewModel.Factory
    private val viewModel: MyViewModel by assistedViewModel {
        viewModelFactory.create(myObject = getMyObjectFromArguments())
    }
}
b

blakelee

12/21/2021, 10:00 PM
Since we have access to SavedStateHandle in ViewModelComponent, maybe I get just set the SavedStateHandle in the fragment, then get it from the SavedStateHandle
4 Views