ViewModelProviders在1.1.0中已弃用


148

在查看的Google文档ViewModel,他们显示了以下有关如何获取的示例代码ViewModel

val model = ViewModelProviders.of(this).get(MyViewModel::class.java)

使用最新的依赖项时android.arch.lifecycle:extensions:1.1.1,没有此类ViewModelProviders

要在文档ViewModelProviders,我看到一个评论说:

在API级别1.1.0中不推荐使用该类。使用ViewModelProvider.AndroidViewModelFactory

问题是,当尝试使用时ViewModelProvider.AndroidViewModelFactory,找不到等效的of方法来获取的实例ViewModel

我尝试做的是:

ViewModelProvider.AndroidViewModelFactory.getInstance(application).create(PlayerViewHolder::class.java)

因此,方法的名称create每次调用时都会得到一个ViewModel的新实例,这不是我想要的。

有什么想法可以替换上面不推荐使用的代码吗?


使用单例模式或更改为AndroidX
Oussema Aroua

Answers:


31

2020-06-16更新目前 ViewModelProviders已弃用,不应再使用。这个问题和答案来自2018年末,当时情况并非如此。这个问题和答案也适用于的较旧的Architecture Components版本ViewModelProviders,而不适用于AndroidX版本。


使用最新的依赖项时android.arch.lifecycle:extensions:1.1.1,没有此类ViewModelProviders

就在这里。为了证明这一点:

  • 在Android Studio 3.2.1中创建一个新项目(使用minSdkVersion21岁的Kotlin ,“空活动”模板)

  • 添加android.arch.lifecycle:extensions:1.1.1app模块的依赖项

这会给你一个app/build.gradle像:

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.commonsware.myandroidarch"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'android.arch.lifecycle:extensions:1.1.1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

然后,您会看到该库显示在该类的“外部库”中:

外部图书馆

您将能够引用该类:

package com.commonsware.myandroidarch

import android.arch.lifecycle.ViewModelProviders
import android.support.v7.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val provider = ViewModelProviders.of(this)
  }
}

转到ViewModelProviders的文档,我看到一条评论说:该类在API级别1.1.0中已弃用。使用ViewModelProvider.AndroidViewModelFactory

该注释在ViewModelProviders.DefaultFactory类条目下面,并且引用该类,而不是ViewModelProviders

文档截图

有什么想法可以替换上面不推荐使用的代码吗?

使用ViewModelProviders


1
@TareKKhoury:那可以解释!跟踪哪个模块需要哪些依赖肯定是一个挑战。我很高兴得知您正在使用它!
CommonsWare

12
这不再是真的,ViewModelProviders.of()不再存在。
EpicPandaForce

321

我使用生命周期扩展2.2.0版本:

implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" 

使用ViewModelProvider构造函数应该可以正常工作。

// With ViewModelFactory   
val viewModel = ViewModelProvider(this, YourViewModelFactory).get(YourViewModel::class.java)


//Without ViewModelFactory
val viewModel = ViewModelProvider(this).get(YourViewModel::class.java)

2020/5/15更新

我找到了另一种优雅的实现方式,Android KTX可以帮助您

implementation "androidx.fragment:fragment-ktx:1.2.4"
val viewmodel: MYViewModel by viewModels()
val viewmodel: MYViewModel by viewModels { myFactory } //With factory

参考: https //developer.android.com/reference/kotlin/androidx/fragment/app/package-summary#viewmodels

2020/06/25:更正了代表的情况


158
我有点讨厌Google持续不断的“折旧”周期。
AFD

3
ViewModelProviders.of()已被弃用。您可以将Fragment或FragmentActivity传递给新的ViewModelProvider(ViewModelStoreOwner)构造函数以实现相同的功能。(aosp / 1009889)
Raghu Krishnan R

31
等效于Java:YourViewModel viewModel = new ViewModelProvider(this).get(YourViewModel.class);
ban-geoengineering

16
我担心是否有一天Google会弃用TextViewEditText并引入一个新的组件。
Pranjal Choladhara

4
androidx lifecycle-viewmodel 2.1.0没有工厂时没有构造函数。简单地使用(this)不起作用。ViewModelProvider(ViewModelStoreOwner,Factory)和ViewModelProvider(ViewModelStore,Factory)是唯一的构造函数
DevinM

70

作为@FantasyFang在他的回答中提到,使用最新版本的lifecycle:lifecycle-extensions在这一刻是2.2.0-alpha03。因此,您应该在build.gradle文件中添加以下行:

implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-alpha03' 

对于使用Java的用户,要解决此问题,请将这些参数直接传递给ViewModelProvider的构造函数

MyViewModel viewModel = new ViewModelProvider(this, myViewModelFactory).get(MyViewModel.class);

或者,如果您不使用工厂,则只需使用:

MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);

没有通过您的工厂对象。


1
您应该在build.gradle中使用以下代码:实现“ androidx.lifecycle:lifecycle-viewmodel:$ lifecycle_version”如developer.android.com/jetpack/androidx/releases/lifecycle中所述。lifecycle -extensions中的API已被弃用。相反,为所需的特定生命周期工件添加依赖项。
肯尼斯·阿戈

40

从2.2.0开始。生命周期扩展已被弃用。请参阅Google文档

这是从页面上剪下来的:

生命周期扩展中的API已被弃用。而是为所需的特定生命周期工件添加依赖项。

新的库是:

// ViewModel and lifecycle support for java
implementation "androidx.lifecycle:lifecycle-viewmodel:${versions.lifecycle}"
implementation "androidx.lifecycle:lifecycle-livedata:${versions.lifecycle}"

// ViewModel and lifecycle support for kotlin
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:${versions.lifecycle}"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:${versions.lifecycle}"

JAVA的新代码:

viewModel = new ViewModelProvider(this).get(MyViewModel.class);

或对于Kotlin:

viewModel = ViewModelProvider(this).get(MyViewModel::class.java)

我们是保持ViewModelProvider的优势还是不得不重新创建它,在这种情况下,所有基础实例也将被销毁。如果想法是观看片段/活动的生命周期,那么我不是重新创建它的原因
TheRealChx101


21

2020年初,Google弃用了ViewModelProviders类在androidx生命周期库的版本2.2.0中。

不再需要使用ViewModelProviders创建ViewModel的实例,您可以将Fragment或Activity实例传递给ViewModelProvider构造函数。

如果您使用如下代码:

val viewModel = ViewModelProviders.of(this).get(CalculatorViewModel::class.java)

您会收到警告, ViewModelProviders已过时。

为避免使用不建议使用的库,请进行以下更改:

  1. 在build.gradle(模块:app)文件中,使用生命周期组件的版本2.2.0:

    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation "androidx.activity:activity-ktx:1.1.0"

    如果要改用Fragment中的ViewModel,请使用

    implementation "androidx.fragment:fragment-ktx:1.2.2"

    fragment-ktx自动包含activity-ktx,因此您无需在依赖项中同时指定两者。

  2. 您需要在android部分中指定Java 8:

    android {
        compileSdkVersion 28
        defaultConfig {
            applicationId "com.kgandroid.calculator"
            minSdkVersion 17
            targetSdkVersion 28
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner 
        "androidx.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 
               'proguard-rules.pro'
            }
        }
    
        kotlinOptions { jvmTarget = "1.8" }
    }
  3. 在片段或活动中,将导入更改为:

    导入androidx.activity.viewModels

  4. 创建ViewModel的代码将变为:

    val viewModel: CalculatorViewModel by viewModels()

    代替

    val viewModel = ViewModelProviders.of(this).get(CalculatorViewModel::class.java)

    将viewModel对象用作:

    val viewModel: CalculatorViewModel by viewModels()
    
    viewModel.newNumber.observe(this, Observer<String> { 
        stringResult -> newNumber.setText(stringResult) 
    })

    其中newNumer是一个LiveData对象

    在要共享活动的ViewModel的Fragment中,您将使用

    val viewModel: CalculatorViewModel by activityViewModels()

这等效于在(不建议使用的)ViewModelProviders.of()函数中传递Activity实例。


17

ViewModelProviders.of()已被弃用。 在此处输入图片说明

直接使用ViewModelProvider构造函数,因为它们现在处理默认的ViewModelProvider.Factory角色。

 mainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);

13

是@Tarek,已弃用。现在使用AndroidX:

val yourViewModel = ViewModelProvider.NewInstanceFactory().create(YourVideoModel::class.java)

5
这个答案是错误的。您应该使用ViewModelProvider(viewModelStoreOwner, factory).get(YourVideoModel::class.java)否则onCleared()将无法正常工作,并且不会在配置更改期间保留ViewModel。不要使用此答案。
EpicPandaForce

12

可能您可以使用:

val viewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(MyViewModel::class.java)

无需添加android.arch.lifecycle:extensions:1.1.1为依赖项。



8

我正在使用android X,也遇到了这个问题。

首先,您应该将以下依赖项添加到您的Gradle

implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version" 

就我而言,$ lifecycle_version是 2.2.0-rc02

第二: 的导入ViewModelProvider应为:

import androidx.lifecycle.ViewModelProvider

比起下面的示例,您可以初始化vIewModel:

val viewModel = ViewModelProvider(this, YourFactoryInstace).get(MainViewModel::class.java)

val viewModel = ViewModelProvider(this).get(MainViewModel::class.java)

谢谢您的回答,但是当我使用它时,viewmodel观察并且字段数据绑定不再起作用
Mosa

我相信androidx.lifecycle:lifecycle-compiler已经过时了androidx.lifecycle:lifecycle-common-java8
Bink

8

实际上,该ViewModelProviders.of()方法在后台执行什么操作?

@Deprecated
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull Fragment fragment) {
    return new ViewModelProvider(fragment);
}

Fragment作为参数,创建ViewModelProvider对象并将片段直接传递给ViewModelProvider构造函数。

我们也可以使用相同的方式。

例如:

OurViewModel mOurViewModel = ViewModelProviders.of(this).get(OurViewModel.class);

后:

OurViewModel mOurViewModel = new ViewModelProvider(this).get(OurViewModel.class);

如果实现Factory,则有另一种方法:ViewModelProvider具有一个既期望a ViewModelStoreOwner又期望a的构造函数Factory
russellhoff


3

我不是专家,但是我有一行代码可以解决Java中的问题。希望这对某人有帮助。

viewModel = 
new ViewModelProvider
.AndroidViewModelFactory(getApplication())
.create(ViewModel.class);

正如我所说,我想提供更多细节,但这为我解决了这个问题。


这段代码是错误的,onCleared()不会以这种方式调用,并且每次都会重新创建ViewModel(不保留用于配置更改)。
EpicPandaForce

您能否再举一个例子说明一下,什么可以解决我的错误?请粘贴说明的引用或使情况更清晰的内容
ZeePee

viewModel = new ViewModelProvider(this).get(MyViewModel.class)。如果您AndroidViewModel没有获得Application,则说明生命周期和活动/片段之间的版本不匹配。
EpicPandaForce

好的,因此调用getApplicationContext是错误的吗?应该只是getContext吗?
ZeePee

1
问题是创建new ViewModelProvider.AndroidViewModelFactory(而不是new ViewModelProvider(
EpicPandaForce

3

用这个:

YourViewModel yourViewModel = new ViewModelProvider.AndroidViewModelFactory(getApplication()).create(YourViewModel.class);

2

您可以改用以下方法:

viewModel= ViewModelProvider(this).get(YourViewModel::class.java)

括号中的“ this”是YourViewModel实例的所有者。


1

这个答案是针对Java的,但您可以理解要点。解决方案是您需要使用ViewModelProvider,因为ViewModelProviders已弃用

//Do not forget import it.
import androidx.lifecycle.AndroidViewModel;

ViewModelProvider.AndroidViewModelFactory(getApplication()).create(YourViewModel.class);

用法示例是:

YourViewModel yourViewModel = new ViewModelProvider.AndroidViewModelFactory(getApplication()).create(YourViewModel.class);

另外,不要忘记更新Gradle Dependencies在此处查看其最新版本

implementation 'androidx.lifecycle:lifecycle-viewmodel:2.2.0'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.2.0'

!!! 但是,请小心,因为一些答案推荐了此解决方案,但它对我不起作用:

yourViewModel = new ViewModelProvider(this).get(YourViewModel.class);

因为当我使用这种方式时,出现以下错误消息:

原因:java.lang.RuntimeException:无法创建com.canerkaseler.mvvmexample.ViewModel类的实例

@canerkaseler


这个答案是错误的。您需要将工厂传递给ViewModelProvider。如果您直接调用createonCleared()则将无法正常工作。
EpicPandaForce

实际上,您实际上只是说过不要使用正确的答案。听起来您androidx.core和您的androidx.lifecycle依赖项之间不匹配。
EpicPandaForce

通常,我将工厂写给ViewModelProvider。但是,您删除了它。ContactViewModel contactViewModel = new ViewModelProvider.AndroidViewModelFactory(getApplication())。create(ContactViewModel.class); 为什么删除我的答案?您输入了错误的代码。
canerkaseler



-2

试试这个...

 LocationViewModel locationViewModel = new ViewModelProvider(this).get(LocationViewModel.class);

-5

它应该这样工作

 viewModel = ViewModelProviders.of(this@MainActivity).get(MainActivityViewModel::class.java)

1
虽然您的代码将实例化为类,但该类不会创建与视图模型的连接,该连接要求视图模型类正确响应生命周期事件。您需要以正确的方式实例化视图模型,以便它们响应并尊重其父母的生命周期,否则每次都将它们重新创建为空白。
肯尼斯·阿戈

正如OP和其他组织指出的那样;ViewModelProviders类已被弃用。请参阅:developer.android.com/reference/androidx/lifecycle/...
肯尼斯·阿尔戈
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.