我正在使用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)
}
}
按下注册按钮时发生崩溃
答案 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的工作原理。