我一直在阅读一些关于Android中MVVM模式的问题,答案和博客,并在我的应用程序中实现了它。
我的应用程序包括一个MainActivity与3标签。每个选项卡的内容是一个片段。
其中一个片段,是存储在Room DB上的用户列表,这是我实现MVVM的地方(实现用户对象,ViewModel, Repository和适配器与RecycleView)。
在相同的片段中,我有一个"add User"按钮,该按钮指向一个新活动,其中呈现公式表以添加新用户。在这个活动中,我想确保用户的全名在保存它之前不存在于我的数据库中。
我试图使用相同的ViewModel来获得完整的用户名全名,但似乎ViewModel从未初始化,我不知道为什么。
我读过一些关于视图模型不能在不同的活动中使用的问题(我在MainActivity中使用它也在AddUser活动
这是我的ViewModel:
class UserViewModel : ViewModel() {
val allUsersLiveData: LiveData<List<User>>
private val repository: UserRepository
init {
Timber.i("Initializing UserViewModel")
repository = UserRepository(UserTrackerApplication.database!!.databaseDao())
allUsersLiveData = repository.getAllUsers()
}
fun getAllUsersFullName(): List<String> {
return allUsersLiveData.value!!.map { it.fullname}
}
和AddUser活动:
class AddUser : AppCompatActivity() {
private lateinit var userList:List<String>
private lateinit var binding: ActivityAddUserBinding
private val userViewModel: UserViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_user)
Timber.i("Add User OnCreate")
binding = ActivityAddUserBinding.inflate(layoutInflater)
setContentView(binding.root)
}
fun addUserClick(v : View){
//someCode
val userName = binding.constraintLayoutAddUser.etUserName!!.text.toString()
if(checkUserExistance(userName)) {
val text: String = String.format(
resources.getString(R.string.repeated_user_name),
userName
Snackbar.make(v, text, Snackbar.LENGTH_LONG).show()
{
else
{
lifecycleScope.launch {
UserTrackerApplication.database!!.databaseDao()
.insertUser(user)
Timber.i("User added!")
}
finish()
}
}
调试,当MainActivity的片段启动时,我看到了日志"Initializing UserViewModel"
,但是当AddUser活动被调用时,我看不到它。所以它似乎没有正确初始化
所以问题是:
- 这是一个好方法吗?我在设计上犯了什么错误?
- 为什么虚拟机没有初始化?
编辑
我忘了添加这个函数。在这里调用userViewModel是我得到错误的地方:
private fun checkUserExistance(userName: String): Boolean {
var result = false
userList = userViewModel.getAllUsersNames()
for (usr in userList)
{
if(usr.uppercase() == userName.uppercase())
{
result = true
break
}
}
return result
}
编辑2
我在我的"onCreate"功能和开始工作:
userViewModel.allUsersLiveData.observe(this, Observer<List<User>>{
it?.let {
// updates the list.
Timber.i("Updating User Names")
userList =userViewModel.getAllUsersNames()
}
})
如果你看一下by viewModels你会看到它是lazy这意味着它将在第一次访问
时进行初始化@MainThread
public inline fun <reified VM : ViewModel> ComponentActivity.viewModels(
noinline factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
val factoryPromise = factoryProducer ?: {
defaultViewModelProviderFactory
}
return ViewModelLazy(VM::class, { viewModelStore }, factoryPromise)
}