How to replace ViewModel dependecy with debug variant in Dagger hilt and consume it in Jetpack compose

78 views Asked by At

I have a an AuthViewModel which handles user authentication related states.

@HiltViewModel
open class AuthViewModel @Inject constructor(
    private val repo: AuthRepository,
    stateHandle: SavedStateHandle
) : ViewModel() {

    fun login() { ... }
    fun confirmLogin() { ... }
}

and consume it in my composables

@Composable
fun LoginScreen(vm: AuthViewModel = hiltViewModel(LocalContext.current as ComponentActivity)) {
    val state by vm.loginUiState.collectAsStateWithLifecycle()
    val credential by vm.credential.collectAsStateWithLifecycle()
    LoginUi(state, credential, vm::login)
}

To make our testing easier for QA, I implemented auto reading of OTP fromn our test server and implemented the same in my Debug source of the AuthViewModel by extending it.

@HiltViewModel
class DebugAuthViewModel @Inject constructor(
    private val repo: DebugAuthRepository,
    stateHandle: SavedStateHandle
) : AuthViewModel(repo, stateHandle) {
    override fun login(mobile: String, onSuccess: () -> Unit) {
        super.login(mobile) {
            getOtp()
        }
    }

    private fun getOtp() {
        // fetch otp from repository
    }
}

Now, I wish to replace AuthViewModel with DebugAuthViewModel for the debug build variant so that I don't ship this debug logic in production build.

How do I do replace that with hilt so that when I read it from the composable, I get the respective ViewModels based on the build variance?

I have tried to create a qualifier as below:

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class ViewModelQualifier(val value: String = BuildConfig.BUILD_TYPE)

And created 2 hilt modules for reach variant

main variant:

@Module
@InstallIn(SingletonComponent::class)
class AuthModule {
    @Provides
    @ViewModelQualifier("release")
    @ActivityScoped
    fun provideAuthViewModel(authViewModel: AuthViewModel): ViewModel {
        return authViewModel
    }
}

And for debug variant:

@Module
@InstallIn(SingletonComponent::class)
object DebugAuthModule {
    @ViewModelQualifier("debug")
    @Provides
    fun provideDebugAuthViewModel(debugAuthViewModel: DebugAuthViewModel): ViewModel {
        return debugAuthViewModel
    }
}

Now how do I tell the hiltViewModel() or any other method to return the correct viewmodel instance based on these qualifiers?

1

There are 1 answers

2
Javad Jafari On

there are much simpler ways to achieve the same result.

  1. if you have build variants for the release and debug build, you could create two files in different source sets and use the correct file in the search build variant.
app
---- src
     ----- main
     ----- debug
           ------- xViewModel
     ----- release
           ------- xViewModel
  1. You can use the BuildConfig to determine which viewModel you should create.

  2. or simply add those extra debug works in the original viewModel with an extra if around it .

if (BuildConfig.BuildType == "debug") {
}