Я пытаюсь поделиться ViewModel между двумя различными действиями. Первое действие - LoginActivity
, там я делаю запрос к API, используя имя пользователя и пароль для получения объекта пользователя. Используя живые данные, этот пользователь затем изменяется в ViewModel. Чтобы проверить, у меня также есть переменная, которая является строкой, и я изменяю ее, как только я делаю вызов API. Мой ViewModel
:
class MainViewModel @Inject constructor() : ViewModel(){
var _request = MutableLiveData<LoginRequest>()
val userLogin: LiveData<LoggedInUser> = Transformations
.switchMap(_request){req ->
MainRepository.authenticatePlease(req.username, req.password)
}
var rando = "rando rando"
fun setUser(username: String, password: String){
val update = LoginRequest(username, password)
rando = "changed"
if(_request.value == update){
return
}
_request.value = update
}
}
Как видите, значение переменной rando
изменено с rando rando
на changed
В моем первом действии это выглядит так:
class LoginActivity : DaggerAppCompatActivity() {
@Inject lateinit var modelFactory: ViewModelProvider.Factory
lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
// AndroidInjection.inject(this)
val button: Button = findViewById(R.id.button)
button.setOnClickListener { onButtonClick() }
val label: TextView = findViewById(R.id.counter)
viewModel = ViewModelProvider(this, modelFactory).get(MainViewModel::class.java)
println("FACTORY: ${modelFactory.hashCode()}")
println("MODEL: ${viewModel.hashCode()}")
viewModel.userLogin.observe(this, Observer{ user ->
println("Debug LOGIN: ${user}")
println("RANDOM: ${viewModel.rando}")
if(user != null){
label.text = user.user.name
redirectToLogin()
}
})
}
fun onButtonClick(){
var username: EditText = findViewById(R.id.username)
var password: EditText = findViewById(R.id.password)
println(username.text.toString())
println(password.text.toString())
viewModel.setUser(username.text.toString(), password.text.toString())
}
fun redirectToLogin(){
println("Login done!")
val intent = Intent(this, SampleActivity::class.java)
intent.putExtra("extra", viewModel.userLogin.value)
startActivity(intent)
}
}
Второе действие выглядит следующим образом:
class SampleActivity : DaggerAppCompatActivity() {
lateinit var viewModel: MainViewModel
@Inject lateinit var modelFactory: ViewModelProvider.Factory
override fun onCreate(savedInstanceState: Bundle?) {
// AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sample)
// val loggedInUser: LoggedInUser? = intent.getParcelableExtra("extra")
// println("extra: $loggedInUser")
viewModel = ViewModelProvider(this, modelFactory).get(MainViewModel::class.java)
println("FACTORY: ${modelFactory.hashCode()}")
println("MODEL: ${viewModel.hashCode()}")
println(" $ WORKS: ${viewModel.userLogin.value.toString()}")
println(" $ WORKS: ${viewModel.userLogin.value}")
println(" $ WORKS: ${viewModel.rando}")
}
}
Следует отметить, что hashcode
для моего ViewModelFactory
одинаково в обоих действиях, но хэш-коды для моделей представления отличаются. Кроме того, переменная rando
во ViewModel равна rando rando
во втором действии, а не changed
Спасибо!
РЕДАКТИРОВАТЬ Вот мой ViewModelFactory
:
@Singleton
class ViewModelProviderFactory @Inject constructor(
private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
val creator = creators[modelClass]
?: throw IllegalArgumentException("Unknown model class $modelClass")
return creator.get() as T
}
AppComponent.kt
:
@Singleton
@Component(
modules = [
AppModule::class,
AndroidInjectionModule::class,
ViewModelModule::class,
ActivityModule::class
]
)
interface AppComponent {
fun inject(app: MainApplication)
@Component.Factory
interface Factory {
fun create(@BindsInstance context: Context): AppComponent
}
}
ActivityModule.kt
:
@Module
abstract class ActivityModule {
@ContributesAndroidInjector
abstract fun contributeLoginActivity(): LoginActivity
@ContributesAndroidInjector
abstract fun contributeSampleActivity(): SampleActivity
}
AppModule.kt
:
@Module(includes = [ViewModelModule::class])
class AppModule {
@Provides
@Named("mainViewModel")
fun provideMainViewModel(): MainViewModel =
MainViewModel()
}
и ViewModelModule.kt
:
@Module
abstract class ViewModelModule {
@Binds
@IntoMap
@ViewModelKey(MainViewModel::class) // PROVIDE YOUR OWN MODELS HERE
internal abstract fun bindMainViewModel(mainViewModel: MainViewModel): ViewModel
@Binds
internal abstract fun bindViewModelProviderFactory(factory: ViewModelProviderFactory): ViewModelProvider.Factory
}
Следует отметить, что в ViewModelModule
я получаю следующее предупреждение Function bindViewModelProviderFactory is never used
и Function bindMainViewModel is never used