Livedata在不同活动中具有不同的价值 [英] Livedata has different values in different activities

查看:48
本文介绍了Livedata在不同活动中具有不同的价值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在kotlin应用程序中使用Android MVVM.我有一个UserViewModel类,其中包含应用程序需要运行的所有与用户相关的数据.

I'm using Android MVVM in my kotlin app. I have a UserViewModel class which has all the user related data the app requires to function.

class UserViewModel(application: Application) : AndroidViewModel(application) {

    val currentUid = MutableLiveData<String>()
    var currentUser = MutableLiveData<User>()
    // More code here...
}

currentUser是在启动时从firestore中获取的,并可供所有活动使用.我想访问User中的currentPlan对象.我这样做:

The currentUser is fetched from firestore at launch and is made available to all the activities. I want to access the currentPlan object inside User. I do this:

someFunc(userViewModel.value!!.currentPlan!!)

这在我的MainActivity中的HomeFragment中很好用. HomeFragment有一个消息按钮,可将用户带到ChatActivty.

This is works fine in my HomeFragment inside my MainActivity. The HomeFragment has a message button which takes user to ChatActivty.

问题是,当我在ChatActivity中执行相同的函数调用时,出现此错误:

The problem is when I execute the same function call in ChatActivity I get this error:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.**, PID: 30420
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.makeshaadi/com.makeshaadi.ChatActivity}: kotlin.KotlinNullPointerException
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2946)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3081)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:201)
        at android.app.ActivityThread.main(ActivityThread.java:6810)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
     Caused by: kotlin.KotlinNullPointerException
        at com.makeshaadi.ChatActivity.onCreate(ChatActivity.kt:52)
        at android.app.Activity.performCreate(Activity.java:7224)
        at android.app.Activity.performCreate(Activity.java:7213)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2926)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3081) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:201) 
        at android.app.ActivityThread.main(ActivityThread.java:6810) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873) 
I/Process: Sending signal. PID: 30420 SIG: 9

为什么userVM.valueChatActivity中变为空.我在做什么错了?

Why does userVM.value becomes null in ChatActivity. What am I doing wrong?

推荐答案

一些理论

有多种方法可以创建ViewModel类的实例(也许我错过了一些):

Some theory

There are multiple ways to create instance of a ViewModel class (maybe I missed some):

// #1 lazy loaded class level variable. 
// Activity serves as view model store
val vm: UserViewModel by activityViewModels()

// #2 lazy loaded class level variable. 
// Activity or Fragment serves as a view model store owner.
// Depends on from which class it is used.
val vm: UserViewModel by viewModels()

// #3 A variable defined in a function scope. 
// `this` is either Activity or a Fragment. The same as #2 but not lazy.
val vm = ViewModelProvider(this).get(UserViewModel::class.java)

// #4 The same as the third option but with factory parameter. 
// Used in cases when view model constructor accepts custom arguments.
// Factory takes care of passing correct parameters.
val vm = ViewModelProvider(this, factory).get(UserViewModel::class.java)

常见的是,您总是隐式或显式使用视图模型存储库所有者.它可以是活动,也可以是片段.只要视图模型存储存在,视图模型就会存在.它受活动/片段"生命周期的约束.当碎片被销毁时,由该碎片创建的所有视图模型也将被销毁(如果有循环引用).活动也是如此.

What is common is that you always implicitly or explicitly use view model store owner. It is either an Activity or a Fragment. View models live as long as the view model store lives. It is constrained by Activity/Fragment lifecycle. When Fragment is destroyed all view models created by that fragment will also be destroyed (if there are circular references). The same goes for the Activity.

这也是创建共享视图模型的方式.片段可以重复使用相同的视图模型,只要它由活动"拥有即可.这就是为什么我们有两个延迟加载函数的原因:by activityViewModels()by viewModels().第一个主要用于共享视图模型.

This is also how shared view models are created. Fragments can re-use the same view model as long as it is owned by the Activity. This is why we have two lazy loading functions: by activityViewModels() and by viewModels(). The first one primarily used for shared view models.

要么不使用视图模型并创建一个单例object,要么不使用一个单例视图模型(强烈建议不要这样做).

Either do not use a view model and create a singleton object or use a singleton view model (highly do not recommend).

如果您的应用程序在其生命周期中共享一些数据,并且您确定应该从一个地方存储和访问这些数据-单例将有所帮助.

If your application shares some data during its lifecycle and you are sure this data should be stored and accessed from a single place - singleton will help.

这就像与数据库建立连接.通常,只有一个打开的连接,或者根据请求打开和关闭它,但是我没有看到后者是通过数据库实现的,通常是通过文件实现的.

This is like having a connection to a database. Usually, there is only one open connection or it is opened and closed by request but I haven't seen latter implementation with databases, usually with files.

我建议使用Kotlin的object:

I suggest using Kotlin's objects:

object MySingleton {
    val currentUid = MutableLiveData<String>()
    var currentUser = MutableLiveData<User>()
    // More code here...
}

这篇关于Livedata在不同活动中具有不同的价值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆