Viewmodel не сохраняет значения после изменения действий с помощью внедрения зависимости кинжала - PullRequest
1 голос
/ 05 февраля 2020

Я пытаюсь поделиться 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

...