fmtjava / Jetpack_GitHub

基于Kotlin + Jetpack全家桶 + Coroutines(协程) + Flutter等架构实现的一款精简版Github客户端项目,望与广大小伙伴一起成长,欢迎start or fork!
MIT License
377 stars 65 forks source link

[疑问]请问怎么做到多页面共享一个viewmodel #9

Closed qq326646683 closed 4 years ago

qq326646683 commented 4 years ago
  1. 需求场景:登录页面给UserViewModel里mUserInfoModel赋值。在Main页面里显示用户信息
  2. 实现:
    
    class LoginActivity : BaseDataBindVMActivity<ActivityLoginBinding>() {
    private val mViewModel: UserViewModel by viewModel()

class MainActivity : BaseDataBindVMActivity() { private val mViewModel: UserViewModel by viewModel()



3. 结果:登录页面可以渲染赋值后的用户信息,Main页面不行
4. 期望:登录页面和Main页面能共享用户信息数据

ps:我打印了两个页面的mViewModel,发现地址不一样,请问如何创建出多个页面共享的mViewModel
fmtjava commented 4 years ago

是要做到数据同步是吧,你可以用LiveData保存用户信息,将LiveData放到一个单例类中,获取或修改都通过单例类就可以了

qq326646683 commented 4 years ago

我用单例试了一下,ui不重新渲染了

object UserInfoUI {
    val mUserModel = MutableLiveData<UserModel>()
}

//activity.kt:
mDataBind.mUserModel = UserInfoUI.mUserModel.value

//userViewModel.kt:
fun getUserInfo() {
        launch {
            UserInfoUI.mUserModel.value = mUserRepository.getUserInfo().obj
        }
    }

//xml:
<variable
            name="mUserModel"
            type="com.jinxian.wenshi.module_user.model.UserModel" />

<TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{mUserModel.phone}"/>

可以提供一下例子吗?最近刚接触android和kotlin,有点不熟

fmtjava commented 4 years ago

UserInfoUI.mUserModel.observe(this, Observer { mDataBind.mUserModel = it }) 试一下这样

qq326646683 commented 4 years ago

也不行哎

fmtjava commented 4 years ago

我写的Demo是下面这样的,不知道是否符合你的需求: `class MainActivity : AppCompatActivity() {

lateinit var mDataBind: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    mDataBind = DataBindingUtil.setContentView(this, R.layout.activity_main)

    UserInfoUI.mUserModel.observe(this, Observer {
        mDataBind.mUserModel = it
    })

}

fun go2Second(view: View) {
    Intent(this, SecondActivity::class.java).also {
        startActivity(it)
    }
}

}

object UserInfoUI { val mUserModel = MutableLiveData() }

class UserModel(val phone: String)`

`class SecondActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_second) }

fun go2First(view: View) {
    val userModel = UserModel("15112453213")
    UserInfoUI.mUserModel.value = userModel
    finish()
}

}`

qq326646683 commented 4 years ago

UserInfoUI.mUserModel.observe(this, Observer { mDataBind.mUserModel = it }) 试一下这样

我又重新试了一下,可以了,多谢多谢,不过有个疑问,为什么你这样可以渲染UI:

   override fun initData() {
        mDataBind.userViewModel = mViewModel
        mViewModel.getUserInfo(mUser)
    }

而我 mDataBind.mUserModel = UserInfoUI.mUserModel.value 不行,为什么非得observe再赋值呢

fmtjava commented 4 years ago

UserInfoUI.mUserModel.observe(this, Observer { mDataBind.mUserModel = it }) 试一下这样

我又重新试了一下,可以了,多谢多谢,不过有个疑问,为什么你这样可以渲染UI:

   override fun initData() {
        mDataBind.userViewModel = mViewModel
        mViewModel.getUserInfo(mUser)
    }

而我 mDataBind.mUserModel = UserInfoUI.mUserModel.value 不行,为什么非得observe再赋值呢

observe是用于订阅数据变化,当数据发生变化后会回到更新,而mDataBind.mUserModel = UserInfoUI.mUserModel.value只是做了一次赋值,并没有订阅事件

qq326646683 commented 4 years ago

我看你先mDataBind.userViewModel = mViewModel ,再去获取信息进行赋值操作,这种是订阅的写法吗?我这边mDataBind.mUserModel = UserInfoUI.mUserModel.value赋值这么就不行呢,感觉写法一样

fmtjava commented 4 years ago

我看你先mDataBind.userViewModel = mViewModel ,再去获取信息进行赋值操作,这种是订阅的写法吗?我这边mDataBind.mUserModel = UserInfoUI.mUserModel.value赋值这么就不行呢,感觉写法一样

你先去了解一下DataBinding与LiveData的使用吧,了解后就应该能明白了