ViewModel 未初始化或问题设计与我的 viewModel

ViewModel not initializing or problem design with my viewModel

我在 Android 中阅读了一些关于 MVVM 模式的问题、答案和博客,并且我已经在我的应用程序中实现了它。

我的应用程序包含一个带有 3 个选项卡的 MainActivity。每个选项卡的内容是一个片段。

其中一个片段是存储在 Room DB 上的用户列表,这是我实现 MVVM 的地方(使用 RecycleView 实现用户对象、ViewModel、存储库和适配器)。

在同一个片段中,我在末尾有一个“添加用户”按钮,它指向一个新的 activity,其中显示了一个用于添加新用户的处方集。在此activity中,我想在保存之前确保用户的全名不存在于我的数据库中。

我试图使用相同的 ViewModel 获取完整的 UserNames 全名,但似乎 ViewModel 从未初始化,我也不知道为什么。

我读过一些关于视图模型不能在不同活动中使用的问题(我在 MainActivity 和 AddUser 中也使用它 activity

这是我的视图模型:

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 activity:

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",调用AddUseractivity时看不到。所以它似乎没有正确初始化。

所以问题:

  1. 这是一个好方法吗?我犯了一些设计错误?
  2. 为什么 VM 没有初始化?

编辑

我忘记添加这个功能了。在这里调用 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 delegate 你会看到它是 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)
}