Livedata在不同活动中具有不同的价值 [英] Livedata has different values in different activities
问题描述
我在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.value
在ChatActivity
中变为空.我在做什么错了?
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 object
s:
object MySingleton {
val currentUid = MutableLiveData<String>()
var currentUser = MutableLiveData<User>()
// More code here...
}
这篇关于Livedata在不同活动中具有不同的价值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!