MVVM从模型到存储库的返回值

时间:2019-07-20 09:59:54

标签: android kotlin mvvm firebase-authentication android-livedata

我正在使用MVVM体系结构来简化项目。然后在这种情况下堆叠,当我必须将Model DataSource(Lambda函数)的值返回到存储库时,ViewModel将观察该存储库。如果这不是理想的话,请纠正我,并给我一些有关android中真正的MVVM的建议。在这种情况下,我只想使用LiveData代替RxJava,因为在Github中许多示例都使用RxJava。 在我的模型中,我有UserDaoImpl类,如下代码段

class UserDaoImpl : UserDao {

    private val resultCreateUser = MutableLiveData<AppResponse>()


    private val mAuth : FirebaseAuth by lazy {
        FirebaseAuth.getInstance()
    }

    override fun createUser(user: User) {

        mAuth.createUserWithEmailAndPassword(user.email, user.password)
            .addOnCompleteListener {

            //I DID NOT REACH THIS LINE

                println("hasilnya ${it.isSuccessful} ")

                if(it.isSuccessful){
                    val appResponse = AppResponse(true, "oke")
                    resultCreateUser.postValue(appResponse)
                }else{
                    val appResponse = AppResponse(false, "not oke -> ${it.result.toString()}")
                    resultCreateUser.postValue(appResponse)
                }
            }
            .addOnFailureListener {

                println("hasilnya ${it.message}")

                val appResponse = AppResponse(false, "not oke -> ${it.message}")
                resultCreateUser.postValue(appResponse)
            }
    }
    override fun getResultCreateUser() = resultCreateUser

}

这是我的存储库代码段

class RegisterRepositoryImpl private constructor(private val userDao: UserDao) : RegisterRepository{

    companion object{
        @Volatile private var instance : RegisterRepositoryImpl? = null

        fun getInstance(userDao: UserDao) = instance ?: synchronized(this){
            instance ?: RegisterRepositoryImpl(userDao).also {
                instance = it
            }
        }

    }
    override fun registerUser(user: User) : LiveData<AppResponse> {

        userDao.createUser(user)
        return userDao.getResultCreateUser() as LiveData<AppResponse>

    }
}

然后这是我的ViewModel

class RegisterViewModel (private val registerRepository: RegisterRepository) : ViewModel() {
    val signUpResult = MutableLiveData<AppResponse>()

    fun registerUser(user: User){

        println(user.toString())

        val response = registerRepository.registerUser(user)
        signUpResult.value = response.value
    }
}

如果我执行上面的代码段,则结果始终为signUpResult中的空指针

这是我的活动

lateinit var viewModel: RegisterViewModel
override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_register)
            initializeUI()

        }

    private fun initializeUI() {
            val factory = InjectorUtils.provideRegisterViewModelFactory()
            viewModel = ViewModelProviders.of(this, factory).get(RegisterViewModel::class.java)
            viewModel.signUpResult.observe(this, Observer {

                //IT always null
                if(it.success){
                    // to HomeActivity
                    Toast.makeText(this, "Success! ${it.msg}", Toast.LENGTH_SHORT).show()
                }else{
                    Toast.makeText(this, "FALSE! ${it.msg}", Toast.LENGTH_SHORT).show()

                }
            })

            register_btn.setOnClickListener {
                        val username = name.text.toString()
                        val email = email.text.toString()
                        val password = password.text.toString()
                        val phone = number.text.toString()
                        val user = User(0, username,"disana", email, password, "disana")
                        viewModel.registerUser(user)
                    }
        }

按下注册按钮时发生崩溃

1 个答案:

答案 0 :(得分:1)

我不确定100%,但是我认为问题出在您的ViewModel中,您试图通过引用传递MutableLiveData。您的活动正在观察signUpResult MutableLiveData,但您从未发布新值,而是试图将LiveData的引用更改为存储库中的那个。

    val signUpResult = MutableLiveData<AppResponse>()

    fun registerUser(user: User){

        println(user.toString())

        val response = registerRepository.registerUser(user)
        signUpResult.value = response.value
    }

我认为这里的解决方案是让ViewModel返回从存储库返回的LiveData。

fun registerUser(user: User): MutableLiveData<AppResponse> {

    println(user.toString())

    return registerRepository.registerUser(user)
}

您需要在Activity中观察函数registerUser(user)。

viewModel.registerUser(user).observe(this, Observer {

但是现在您遇到了另一个问题。通过此示例,您将在每次单击按钮时触发观察方法。因此,您需要在存储库中拆分函数,仅需要一个函数返回userDao.getResultCreateUser() as LiveData<AppResponse>,另一个函数来触发userDao.create(user)。 这样您就可以在存储库中实现两个功能

override fun observeRegistrationResponse() : LiveData<AppResponse> {
    return userDao.getResultCreateUser() as LiveData<AppResponse>
}
override fun registerUser(user: User) {
    userDao.createUser(user)
}

现在在ViewModel中,您还需要为观察结果和发送注册请求提供单独的功能。

fun observeRegistrationResponse(): LiveData<AppResponse> {
    return registerRepository.observeRegistrationResponse()
}

fun registerUser(user: User){
    println(user.toString())
    registerRepository.registerUser(user)
}

最后,您可以在函数initializeUI中观察

viewModel.observeRegistrationResponse().observe(this, Observer {

然后点击按钮发送注册请求

viewModel.registerUser(user)

很抱歉,我的回答很长,但是我试图解释为什么您需要更改方法。我希望我能帮助您了解LiveData的工作原理。