ViewModelProviders在1.1.0版本中已被弃用。

244

查看Google文档中关于ViewModel的内容,其中提供了以下示例代码来获取ViewModel

val model = ViewModelProviders.of(this).get(MyViewModel::class.java)
当使用最新的依赖项 android.arch.lifecycle:extensions:1.1.1 时,没有这样的类 ViewModelProviders
查看 ViewModelProviders文档时,我看到了以下注释:

This class was deprecated in API level 1.1.0. Use ViewModelProvider.AndroidViewModelFactory

问题在于,当尝试使用 ViewModelProvider.AndroidViewModelFactory 时,找不到等效的方法来获取 ViewModel 的实例。
我尝试做的事情:
ViewModelProvider.AndroidViewModelFactory.getInstance(application).create(PlayerViewHolder::class.java)
因此,由于方法的名称create,每次调用它时我都会得到一个新的ViewModel实例,这不是我想要的。您有任何替代上述弃用代码的想法吗?
替换上述废弃代码的方法是什么?

使用单例模式或切换到AndroidX。 - Oussema Aroua
31个回答

475

我使用lifecycle-extensions 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:更正了委托的大小写


261
我有点厌烦 Google 不断进行的“折旧”周期。 - Andrei Drynov
4
ViewModelProviders.of()已被弃用。您可以将Fragment或FragmentActivity传递给新的ViewModelProvider(ViewModelStoreOwner)构造函数,以实现相同的功能。(aosp/1009889) - Raghu Krishnan R
47
Java等效代码:YourViewModel viewModel = new ViewModelProvider(this).get(YourViewModel.class); - ban-geoengineering
34
我担心有一天Google会废弃TextViewEditText并引入一个新的组件。 - Pranjal Choladhara
4
androidx lifecycle-viewmodel 2.1.0没有不带工厂的构造函数。仅使用(this)无法工作。 ViewModelProvider(ViewModelStoreOwner,Factory)和ViewModelProvider(ViewModelStore,Factory)是唯一的构造函数。 - DevinM
显示剩余7条评论

104

正如@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 中使用以下代码:implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"如 https://developer.android.com/jetpack/androidx/releases/lifecycle 所述,lifecycle-extensions 中的 API 已被弃用。相反,添加你需要的特定生命周期依赖项。 - Kenneth Argo

76

导入

已废弃自:

<strike>import androidx.lifecycle.ViewModelProviders;</strike>

收件人:

import androidx.lifecycle.ViewModelProvider;

使用

从以下版本起已弃用:

<strike>ViewModelProviders.of</strike>(this, provider).get(VM::class.java)

收件人:

ViewModelProvider(this, provider).get(VM::class.java)

5
正是我在寻找的。 - Rahul Bali
1
完美。这应该是被接受的答案。 - Oke Uwechue

61

从2.2.0版本开始,lifecycle-extensions已被弃用。请参考Google文档

以下是页面的摘要:

在lifecycle-extensions中的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
1
谢谢您包含Java - 我们中的一些人仍然必须维护旧代码。 - zkon

47

更新于2020年6月16日目前ViewModelProviders已经被弃用,不应再使用。这个问题和答案是在2018年末发布的,当时还没有这种情况。这个问题和答案也适用于旧版架构组件中的ViewModelProviders,而不是AndroidX版。


当使用最新的依赖项android.arch.lifecycle:extensions:1.1.1时,不存在ViewModelProviders类。
是的,存在。为了证明这一点:
  • 在Android Studio 3.2.1中创建一个新项目(使用Kotlin,minSdkVersion 21,“空活动”模板)

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

这将为您提供一个像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'
}

然后你会看到那个库与该类显示在“外部库”中:

External Libraries

你将能够引用那个类:

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 level 1.1.0中已被弃用。使用ViewModelProvider.AndroidViewModelFactory代替。该注释位于ViewModelProviders.DefaultFactory类条目下方,并指的是该类,而不是ViewModelProviders本身。

Documentation Screenshot

有什么想法来替换上面被弃用的代码吗?使用ViewModelProviders

1
@TareKKhoury:这就可以解释了!跟踪哪些模块需要哪些依赖项确实是一个挑战。我很高兴听到你已经解决了问题! - CommonsWare
32
这个说法不再正确,ViewModelProviders.of() 已经不存在了。 - EpicPandaForce

37

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(Module: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,因此您不需要在依赖项中同时指定两者。

您需要在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" }
}
  • 在您的Fragment或Activity中,将导入更改为:

    import androidx.activity.viewModels

  • 创建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) 
    })
    

    其中newNumber是LiveData对象

    如果您想在片段中共享活动的ViewModel,则可以使用以下方法:

    val viewModel: CalculatorViewModel by activityViewModels()
    
  • 这相当于在(deprecated) ViewModelProviders.of()函数中传递Activity实例。


    26

    ViewModelProviders.of()已被弃用。 enter image description here

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

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

    20

    也许你可以直接使用:

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

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


    15

    实际上,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);
    

    1
    如果您实现了一个工厂,您还有另一种方法:ViewModelProvider有一个构造函数,它需要一个ViewModelStoreOwner和一个Factory - joninx

    13

    是的 @Tarek,它已被弃用。现在请使用 AndroidX:

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

    17
    这个答案是错误的。你应该使用ViewModelProvider(viewModelStoreOwner, factory).get(YourVideoModel::class.java),否则你的onCleared()方法将无法正确工作,而且ViewModel在配置更改时也无法保留。不要使用这个答案。 - EpicPandaForce

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接