如何在 AndroidX 中实例化 ViewModel?
how to instantiate ViewModel In AndroidX?
我想在 Activity 中使用 androidx 库
初始化 ViewModel
我已经尝试了文档中所说的,但它不起作用。 “.of”未解析。
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import com.example.myapplication.databinding.ActivityMainBinding`
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainBinding = DataBindingUtil.setContentView(
this, R.layout.activity_main)
binding.setLifecycleOwner(this)
var model = ViewModelProvider.of(this).get(SheduleViewModel::class.java)
}
}
of没有解决,在androidx中可能还有别的办法
更新的答案:
事情发生了一点变化,因为以前需要依赖 - ViewModelProviders
- got deprecated(有关详细信息,请参阅旧答案)。您现在可以直接使用 ViewModelProvider
构造函数。
所以,在这种情况下,答案是:
private val viewModel = ViewModelProvider(this).get(SheduleViewModel::class.java)
但是请注意,如果您包含 androidx.activity:activity-ktx:$Version
依赖项(一些常用的 AndroidX 依赖项已经为您包含),您可以使用 属性 委托:
private val viewModel: SheduleViewModel by viewModels()
内部将使用 ViewModelProvider
并将您的 ViewModel
范围限定为 Activity
。这只是编写相同内容的一种更简洁的方式。您可以通过包含 androidx.fragment:fragment-ktx:$Version
依赖项来对 Fragment
执行相同的操作(同样,通常已经包含在其他 AndroidX 依赖项中)。
ViewModelProvider
构造函数和 by viewModels()
都接受一个工厂作为参数(对注入你的 ViewModel
很有用):
private val viewModel =
ViewModelProvider(this, viewModelFactory).get(SheduleViewModel::class.java)
和
private val viewModel: SheduleViewModel by viewModels { viewModelFactory }
使用最适合你的那个。
旧答案:
添加 androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionsVersion
依赖项以导入 ViewModelProviders
.
(如何) 使用来自 Android 架构组件的 ViewModel
:
添加 Google Maven 存储库(可选,只需验证)
Android Studio 项目默认未配置为访问此存储库。
要将其添加到您的项目中,请打开项目 (不是您的应用程序或模块的文件)build.gradle
文件 并添加 google()
仓库如下图:
allprojects {
repositories {
google()
jcenter()
}
}
正在声明依赖关系
打开您的应用级 build.gradle
文件,
转到dependencies{}
块
把implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
换成AndroidX版本,$lifecycle_version这里是最新版本定义。
对于 Pre-AndroidX 使用 implementation "android.arch.lifecycle:viewmodel:1.1.1"
(我猜 1.1.1 是这个工件的最后一个版本。)
在你的activity中,像这样使用语法
导入此 class:
import androidx.lifecycle.ViewModelProviders;
对于 AndroidX
import android.arch.lifecycle.ViewModelProviders;
当使用 Pre-AndroidX
并获得您的 ViewModel
如下所示
ViewModelProviders.of(this).get(ProfileObservableViewModel::class.java)
// Kotlin 语法
---- 或 ----
ViewModelProviders.of(this).get(ProfileObservableViewModel.class);
// Java 语法
正在将 ViewModel 更新到 Lifecycle Version 2.2.0 及更高版本
ViewModels (VM) 理论上可以使用 Kotlin 扩展库 import androidx.fragment.app.viewModels
方法 by viewmodels()
初始化为 class 级实例变量。通过将 VM 初始化为 class 级实例变量,可以在 class 中访问它。
问题:将 VM 初始化为 class 级实例变量而不是内部 onCreate
是否有缺点?
在 onCreate
中使用扩展函数创建 VM 时,VM 的作用域仅在 onCreate
内,并且需要额外的代码来重新分配 class 级别的实例变量。
查看文档
将 VM 初始化为 Class 实例值
class Fragment : Fragment() {
private val viewModel: SomeViewModel by viewModels()
private fun observeViewState() {
viewModel.feedViewState.observe(viewLifecycleOwner) { viewState ->
//viewState used here.
}
}
}
在 onCreate 中初始化 VM 并重新分配 Class 实例 Var
class Fragment : Fragment() {
private lateinit var viewModel: SomeViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val viewModel: ContentViewModel by viewModels()
this.viewModel = viewModel
}
private fun observeViewState() {
viewModel.feedViewState.observe(viewLifecycleOwner) { viewState ->
//viewState used here.
}
}
}
通过 Arguments/Parameters
// Override ViewModelProvider.NewInstanceFactory to create the ViewModel (VM).
class SomeViewModelFactory(private val someString: String): ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel?> create(modelClass: Class<T>): T = SomeViewModel(someString) as T
}
class SomeViewModel(private val someString: String) : ViewModel() {
init {
//TODO: Use 'someString' to init process when VM is created. i.e. Get data request.
}
}
class Fragment: Fragment() {
// Create VM in activity/fragment with VM factory.
val someViewModel: SomeViewModel by viewModels { SomeViewModelFactory("someString") }
}
使用 Arguments/Parameters
启用 SavedState
class SomeViewModelFactory(
private val owner: SavedStateRegistryOwner,
private val someString: String) : AbstractSavedStateViewModelFactory(owner, null) {
override fun <T : ViewModel?> create(key: String, modelClass: Class<T>, state: SavedStateHandle) =
SomeViewModel(state, someString) as T
}
class SomeViewModel(private val state: SavedStateHandle, private val someString: String) : ViewModel() {
val feedPosition = state.get<Int>(FEED_POSITION_KEY).let { position ->
if (position == null) 0 else position
}
init {
//TODO: Use 'someString' to init process when VM is created. i.e. Get data request.
}
fun saveFeedPosition(position: Int) {
state.set(FEED_POSITION_KEY, position)
}
}
class Fragment: Fragment() {
// Create VM in activity/fragment with VM factory.
val someViewModel: SomeViewModel by viewModels { SomeViewModelFactory(this, "someString") }
private var feedPosition: Int = 0
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
someViewModel.saveFeedPosition((contentRecyclerView.layoutManager as LinearLayoutManager)
.findFirstVisibleItemPosition())
}
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
feedPosition = someViewModel.feedPosition
}
}
PS。这是给那些正在使用 java 并且像我一样卡住了一段时间的人,这个 SO 答案一直出现在 google 中。
显然,API 从这个日期(2020 年 5 月 6 日)开始发生了变化,我必须这样做才能让它正常工作。
// 1. Create a ViewModel Class Let's call it AppStateViewModel
// 2. Put below code Inside Activity onCreate like this:
ViewModelProvider.Factory factory = new ViewModelProvider.NewInstanceFactory();
appStateManager = new ViewModelProvider(this, factory).get(AppStateViewModel.class);
ViewModelProviders: This class is deprecated. Use the constructors for ViewModelProvider directly.
Kotlin
中的示例
这是您可以直接使用 ViewModelProvider 的方式:
如果您的视图模型正在扩展 AndroidViewModel with just one argument, the app - then you can use the default AndroidViewModelFactory 并且您不必编写新工厂。示例:
// Activity / fragment class
private lateinit var viewModel: MyOwnAndroidViewModel
// onCreate
viewModel = ViewModelProvider(
this,
ViewModelProvider.AndroidViewModelFactory(application)
).get(MyOwnAndroidViewModel::class.java)
如果您的视图模型仅扩展 ViewModel without extra arguments then use the NewInstanceFactory()。
// Activity / fragment class
private lateinit var viewModel: MyOwnViewModel
// onCreate
viewModel = ViewModelProvider(
this,
ViewModelProvider.NewInstanceFactory()
).get(MyOwnViewModel::class.java)
上面亚当的回答也涵盖了其他变体。
免责声明:仍在学习基础 Android 开发 - 如果代码有任何问题,请在评论中告诉我。
对我来说,唯一有效的方法是:
implementation 'androidx.fragment:fragment:1.2.4'
在 app.gradle 下的 dependencies
中粘贴以下或类似内容(与您的设置相关)
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
将下面的代码粘贴到 build.gradle(:app)
implementation 'androidx.fragment:fragment-ktx:1.4.1'
在您的应用 gradle 文件中,确保您已添加以下依赖项:
Activity 使用:
implementation "androidx.activity:activity-ktx:1.4.1"
片段使用:
implementation 'androidx.fragment:fragment:1.4.1'
我添加了这个依赖的最后一个版本
https://developer.android.com/kotlin/ktx/extensions-list
实施“androidx.activity:activity-ktx:1.4.0”
我想在 Activity 中使用 androidx 库
初始化 ViewModel我已经尝试了文档中所说的,但它不起作用。 “.of”未解析。
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import com.example.myapplication.databinding.ActivityMainBinding`
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainBinding = DataBindingUtil.setContentView(
this, R.layout.activity_main)
binding.setLifecycleOwner(this)
var model = ViewModelProvider.of(this).get(SheduleViewModel::class.java)
}
}
of没有解决,在androidx中可能还有别的办法
更新的答案:
事情发生了一点变化,因为以前需要依赖 - ViewModelProviders
- got deprecated(有关详细信息,请参阅旧答案)。您现在可以直接使用 ViewModelProvider
构造函数。
所以,在这种情况下,答案是:
private val viewModel = ViewModelProvider(this).get(SheduleViewModel::class.java)
但是请注意,如果您包含 androidx.activity:activity-ktx:$Version
依赖项(一些常用的 AndroidX 依赖项已经为您包含),您可以使用 属性 委托:
private val viewModel: SheduleViewModel by viewModels()
内部将使用 ViewModelProvider
并将您的 ViewModel
范围限定为 Activity
。这只是编写相同内容的一种更简洁的方式。您可以通过包含 androidx.fragment:fragment-ktx:$Version
依赖项来对 Fragment
执行相同的操作(同样,通常已经包含在其他 AndroidX 依赖项中)。
ViewModelProvider
构造函数和 by viewModels()
都接受一个工厂作为参数(对注入你的 ViewModel
很有用):
private val viewModel =
ViewModelProvider(this, viewModelFactory).get(SheduleViewModel::class.java)
和
private val viewModel: SheduleViewModel by viewModels { viewModelFactory }
使用最适合你的那个。
旧答案:
添加 androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionsVersion
依赖项以导入 ViewModelProviders
.
(如何) 使用来自 Android 架构组件的 ViewModel
:
添加 Google Maven 存储库(可选,只需验证)
Android Studio 项目默认未配置为访问此存储库。
要将其添加到您的项目中,请打开项目 (不是您的应用程序或模块的文件)
build.gradle
文件 并添加google()
仓库如下图:allprojects { repositories { google() jcenter() } }
正在声明依赖关系
打开您的应用级
build.gradle
文件,转到
dependencies{}
块把
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
换成AndroidX版本,$lifecycle_version这里是最新版本定义。对于 Pre-AndroidX 使用
implementation "android.arch.lifecycle:viewmodel:1.1.1"
(我猜 1.1.1 是这个工件的最后一个版本。)在你的activity中,像这样使用语法
导入此 class:
import androidx.lifecycle.ViewModelProviders;
对于 AndroidXimport android.arch.lifecycle.ViewModelProviders;
当使用 Pre-AndroidX并获得您的
ViewModel
如下所示ViewModelProviders.of(this).get(ProfileObservableViewModel::class.java)
// Kotlin 语法---- 或 ----
ViewModelProviders.of(this).get(ProfileObservableViewModel.class);
// Java 语法
正在将 ViewModel 更新到 Lifecycle Version 2.2.0 及更高版本
ViewModels (VM) 理论上可以使用 Kotlin 扩展库 import androidx.fragment.app.viewModels
方法 by viewmodels()
初始化为 class 级实例变量。通过将 VM 初始化为 class 级实例变量,可以在 class 中访问它。
问题:将 VM 初始化为 class 级实例变量而不是内部 onCreate
是否有缺点?
在 onCreate
中使用扩展函数创建 VM 时,VM 的作用域仅在 onCreate
内,并且需要额外的代码来重新分配 class 级别的实例变量。
查看文档
将 VM 初始化为 Class 实例值
class Fragment : Fragment() {
private val viewModel: SomeViewModel by viewModels()
private fun observeViewState() {
viewModel.feedViewState.observe(viewLifecycleOwner) { viewState ->
//viewState used here.
}
}
}
在 onCreate 中初始化 VM 并重新分配 Class 实例 Var
class Fragment : Fragment() {
private lateinit var viewModel: SomeViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val viewModel: ContentViewModel by viewModels()
this.viewModel = viewModel
}
private fun observeViewState() {
viewModel.feedViewState.observe(viewLifecycleOwner) { viewState ->
//viewState used here.
}
}
}
通过 Arguments/Parameters
// Override ViewModelProvider.NewInstanceFactory to create the ViewModel (VM).
class SomeViewModelFactory(private val someString: String): ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel?> create(modelClass: Class<T>): T = SomeViewModel(someString) as T
}
class SomeViewModel(private val someString: String) : ViewModel() {
init {
//TODO: Use 'someString' to init process when VM is created. i.e. Get data request.
}
}
class Fragment: Fragment() {
// Create VM in activity/fragment with VM factory.
val someViewModel: SomeViewModel by viewModels { SomeViewModelFactory("someString") }
}
使用 Arguments/Parameters
启用 SavedStateclass SomeViewModelFactory(
private val owner: SavedStateRegistryOwner,
private val someString: String) : AbstractSavedStateViewModelFactory(owner, null) {
override fun <T : ViewModel?> create(key: String, modelClass: Class<T>, state: SavedStateHandle) =
SomeViewModel(state, someString) as T
}
class SomeViewModel(private val state: SavedStateHandle, private val someString: String) : ViewModel() {
val feedPosition = state.get<Int>(FEED_POSITION_KEY).let { position ->
if (position == null) 0 else position
}
init {
//TODO: Use 'someString' to init process when VM is created. i.e. Get data request.
}
fun saveFeedPosition(position: Int) {
state.set(FEED_POSITION_KEY, position)
}
}
class Fragment: Fragment() {
// Create VM in activity/fragment with VM factory.
val someViewModel: SomeViewModel by viewModels { SomeViewModelFactory(this, "someString") }
private var feedPosition: Int = 0
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
someViewModel.saveFeedPosition((contentRecyclerView.layoutManager as LinearLayoutManager)
.findFirstVisibleItemPosition())
}
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
feedPosition = someViewModel.feedPosition
}
}
PS。这是给那些正在使用 java 并且像我一样卡住了一段时间的人,这个 SO 答案一直出现在 google 中。
显然,API 从这个日期(2020 年 5 月 6 日)开始发生了变化,我必须这样做才能让它正常工作。
// 1. Create a ViewModel Class Let's call it AppStateViewModel
// 2. Put below code Inside Activity onCreate like this:
ViewModelProvider.Factory factory = new ViewModelProvider.NewInstanceFactory();
appStateManager = new ViewModelProvider(this, factory).get(AppStateViewModel.class);
ViewModelProviders: This class is deprecated. Use the constructors for ViewModelProvider directly.
Kotlin
中的示例这是您可以直接使用 ViewModelProvider 的方式:
如果您的视图模型正在扩展 AndroidViewModel with just one argument, the app - then you can use the default AndroidViewModelFactory 并且您不必编写新工厂。示例:
// Activity / fragment class
private lateinit var viewModel: MyOwnAndroidViewModel
// onCreate
viewModel = ViewModelProvider(
this,
ViewModelProvider.AndroidViewModelFactory(application)
).get(MyOwnAndroidViewModel::class.java)
如果您的视图模型仅扩展 ViewModel without extra arguments then use the NewInstanceFactory()。
// Activity / fragment class
private lateinit var viewModel: MyOwnViewModel
// onCreate
viewModel = ViewModelProvider(
this,
ViewModelProvider.NewInstanceFactory()
).get(MyOwnViewModel::class.java)
上面亚当的回答也涵盖了其他变体。
免责声明:仍在学习基础 Android 开发 - 如果代码有任何问题,请在评论中告诉我。
对我来说,唯一有效的方法是:
implementation 'androidx.fragment:fragment:1.2.4'
在 app.gradle 下的 dependencies
中粘贴以下或类似内容(与您的设置相关)implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
将下面的代码粘贴到 build.gradle(:app)
implementation 'androidx.fragment:fragment-ktx:1.4.1'
在您的应用 gradle 文件中,确保您已添加以下依赖项:
Activity 使用:
implementation "androidx.activity:activity-ktx:1.4.1"
片段使用:
implementation 'androidx.fragment:fragment:1.4.1'
我添加了这个依赖的最后一个版本 https://developer.android.com/kotlin/ktx/extensions-list
实施“androidx.activity:activity-ktx:1.4.0”