简体   繁体   English

如何创建可以从 ViewModel 和 Activity 访问的 function?

[英]How can I create a function that I can access from both a ViewModel and Activity?

I am building an android app that has a MainActivity and several fragments.我正在构建一个具有 MainActivity 和几个片段的 android 应用程序。 I am using a ViewModel and ViewModelFactory for each of the fragments.我为每个片段使用 ViewModel 和 ViewModelFactory。 I need to create a function that will perform network requests and would like to have it available in one of the fragments so I can display a progress bar to the user.我需要创建一个 function 来执行网络请求,并希望它在其中一个片段中可用,这样我就可以向用户显示一个进度条。 I would also like to access this function from MainActivity in the override function onOptionsItemSelected when a user clicks on the button in the menu in the top right.当用户单击右上角菜单中的按钮时,我还想在覆盖 function onOptionsItemSelected 中从 MainActivity 访问此 function。 When called from this button everything should be in the background and there is no need to show the user anything until the task is completed.从这个按钮调用时,一切都应该在后台,并且在任务完成之前不需要向用户显示任何内容。

I have tried two approaches.我尝试了两种方法。

  1. Place the function inside the ViewModel.将 function 放在 ViewModel 中。 This works perfect for when called from the fragment and everything works.这非常适合从片段调用并且一切正常。 But when calling from the Main activity I cannot seem to reference the ViewModel correctly.但是当从 Main 活动调用时,我似乎无法正确引用 ViewModel。

I placed this in MainActivity before onCreate我在 onCreate 之前把它放在 MainActivity

private lateinit var syncViewModel: SyncViewModel

And this in onCreate这在 onCreate

syncViewModel = ViewModelProvider(this).get(SyncViewModel::class.java)

And I get the below error message.我收到以下错误消息。

java.lang.RuntimeException: Unable to start activity ComponentInfo java.lang.RuntimeException: Cannot create an instance of class com. java.lang.RuntimeException: Unable to start activity ComponentInfo java.lang.RuntimeException: Cannot create an instance of class com. . . ._.SyncViewModel ._.SyncViewModel

How can I access the already created ViewModel from the activity instead of creating one?如何从活动中访问已经创建的 ViewModel 而不是创建一个?

  1. So my second try was to place this function in a separate file.所以我的第二次尝试是将这个 function 放在一个单独的文件中。 I could then access this from the ViewModel and the MainActivity.然后我可以从 ViewModel 和 MainActivity 访问它。 But I could not find a way to update the progress bar in the ViewModel.但是我找不到更新 ViewModel 中进度条的方法。

In the ViewModel I have the below, and then the xml in this fragment references this syncProgress value.在 ViewModel 中,我有以下内容,然后这个片段中的 xml 引用了这个 syncProgress 值。

private var _syncProgress = MutableLiveData<Int>()

val syncProgress: LiveData<Int> = _syncProgress

What am I missing to connect this separate function to be able to update the values in my ViewModel?我缺少什么来连接这个单独的 function 以便能够更新我的 ViewModel 中的值?

It seems like option #1 is the right way to do this, but maybe there is a third way that I dont know about that would be better!似乎选项#1是正确的方法,但也许有第三种我不知道的方法会更好! Any help is appreciated!任何帮助表示赞赏!

Update 1更新 1

My ViewModel is defined as我的 ViewModel 定义为

class SyncViewModel(
val database: RoomDatabase,
application: Application) : AndroidViewModel(application) {

And in the fragment as在片段中

// Create an Instance of the ViewModel Factory
val dataSource = RoomDatabase.getDatabase(application)
val viewModelFactory = SyncViewModelFactory(dataSource, application)

private lateinit var syncViewModel: SyncViewModel
syncViewModel = ViewModelProvider(this,viewModelFactory).get(SyncViewModel::class.java)

But I am not sure how I need to modify the SyncViewModel in MainActivity?但我不确定我需要如何修改 MainActivity 中的 SyncViewModel?

I would follow your option 1, and use view model provider delegates to simplify getting your reference.我会遵循您的选项 1,并使用视图 model 提供者代表来简化获取您的参考。 You should specify an Activity-scoped ViewModel in the Fragment so it gets the same instance that the Activity gets.您应该在 Fragment 中指定一个 Activity 范围的 ViewModel,以便它获得与 Activity 相同的实例。

In your Activity:在您的活动中:

private val syncViewModel: SyncViewModel by viewModels()

In your Fragment:在你的片段中:

private val syncViewModel: SyncViewModel by activityViewModels()

Since your database can be acquired using the Application instance, you can avoid creating a factory by moving it out of the constructor like this:由于可以使用 Application 实例获取数据库,因此可以通过将其移出构造函数来避免创建工厂,如下所示:

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

    val database = RoomDatabase.getDatabase(application)

If you do want to continue using your factory, you can pass it as a parameter to the delegate functions, for example:如果您确实想继续使用您的工厂,可以将其作为参数传递给委托函数,例如:

private val dataSource = RoomDatabase.getDatabase(application)
private val syncViewModel: SyncViewModel by activityViewModels(SyncViewModelFactory(dataSource, application))

If I understand correctly the function should be outside of the ViewModel because it has to be accessed in other places too.如果我理解正确,function 应该在 ViewModel 之外,因为它也必须在其他地方访问。

The LiveData in the ViewModel won't get updated on the state of the function but one way to fix this would be to just make the ViewModel immediately "listen" to whatever the function's current state is. ViewModel 中的 LiveData 不会在 function 的 state 上更新,但解决此问题的一种方法是让 ViewModel 立即“监听”函数当前的 Z9ED39E2EA931586B6EZEFA 是什么。

Let's say you would normally update the value/progress from 0 to 100 in a Repository, update a LiveData object with that progress and make the ViewModel or/and Activity listen to it.假设您通常会在存储库中将值/进度从 0 更新到 100,用该进度更新 LiveData object 并让 ViewModel 或/和 Activity 监听它。 LiveData in Repositories isn't something that's perfect but it seems like a solution based on what I read.存储库中的 LiveData 不是完美的,但它似乎是基于我阅读的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我如何使用视图模型从另一个片段访问 function - how can i use a viewmodel to access a function from another fragement 如何从服务中访问我的活动的 ViewModel? - How can I access my activity's ViewModel from within a service? 如何从另一个活动刷新 viewModel 实时数据 - How can I refresh viewModel livedata from another activity 如何从另一个活动访问活动的视图 - How can I access a view of an activity from another activity 我如何从android中的另一个活动调用活动中的函数? - How can i call a function in activity from another activity in android? 我可以在活动和服务之间共享ViewModel吗? - Can I share a ViewModel between an activity and a service? 我如何同时具有启动活动和介绍活动? - How can I have Both Splash Activity and Intro Activity? 是否有必要始终创建一个视图模型来执行简单的查询,或者我可以从我的存储库访问数据库吗? - Is it necessary to always create a viewmodel to perform a simple query or can I access the database from my repository? 如何使用LiveData和ViewModel类将数据从Activity发送到Fragment - How can i send data from Activity to Fragment using LiveData and ViewModel class 如何以干净简单的方式将数据从 ViewModel 获取到 Activity 或 Fragment? - How can I get data from ViewModel to Activity or Fragment in clean and simple way?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM