O ViewModelProviders está obsoleto no 1.1.0

148

Olhando para os documentos do Google para ViewModel, eles mostram a seguir código de exemplo sobre como obter um ViewModel:

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

Ao usar a dependência mais recente, android.arch.lifecycle:extensions:1.1.1não existe essa classe ViewModelProviders.

Indo para a documentação de ViewModelProviders, vi um comentário dizendo:

Esta classe foi descontinuada no nível de API 1.1.0. Use ViewModelProvider.AndroidViewModelFactory

O problema é que, ao tentar usar ViewModelProvider.AndroidViewModelFactory, não é possível encontrar um ofmétodo equivalente para obter a instância do ViewModel.

O que eu tentei fazer:

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

Portanto, o nome do método create, eu sempre recebo uma nova instância do ViewModel, o que não é o que estou procurando.

Alguma idéia de qual é a substituição do código obsoleto acima?

TareK Khoury
fonte
use padrão singleton ou altere para AndroidX
Oussema Aroua

Respostas:

31

ATUALIZAÇÃO 2020-06-16 : Atualmente ViewModelProviders está obsoleto e não deve mais ser usado. Esta pergunta e resposta foram do final de 2018, quando não foi esse o caso. Esta pergunta e resposta também são para a edição mais antiga do Architecture Components ViewModelProviders, e não para a edição AndroidX.


Ao usar a dependência mais recente, android.arch.lifecycle:extensions:1.1.1não existe essa classe ViewModelProviders.

Sim existe. Para demonstrar isso:

  • Crie um novo projeto no Android Studio 3.2.1 (com Kotlin, minSdkVersion21, modelo "atividade vazia")

  • Adicione android.arch.lifecycle:extensions:1.1.1às dependências do appmódulo

Isso lhe dará um app/build.gradlelike:

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'
}

Você verá a biblioteca exibida em "Bibliotecas externas" com essa classe:

Bibliotecas externas

E você poderá fazer referência a essa classe:

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)
  }
}

Indo para a documentação de ViewModelProviders, vi um comentário dizendo: Esta classe foi descontinuada no nível de API 1.1.0. Use ViewModelProvider.AndroidViewModelFactory

Esse comentário está abaixo da ViewModelProviders.DefaultFactoryentrada da classe e se refere a essa classe, não ViewModelProviders:

Captura de tela da documentação

Alguma idéia de qual é a substituição do código obsoleto acima?

Use ViewModelProviders.

CommonsWare
fonte
1
@TareKKhoury: Isso explicaria isso! Manter o controle de quais módulos precisam de quais dependências definitivamente pode ser um desafio. Fico feliz em saber que você conseguiu!
CommonsWare
13
Isso não é mais verdade, ViewModelProviders.of()não existe mais.
EpicPandaForce
323

Eu uso a 2.2.0versão de extensões do ciclo de vida :

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

Deve ser trabalho, usando o ViewModelProviderconstrutor.

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


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

2020/5/15 Atualizar

Acho outra maneira elegante de conseguir, o Android KTX pode ajudar

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

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

2020/06/25: corrigido o caso do delegado

Fantasy Fang
fonte
160
Estou meio cansado do constante ciclo de "depreciação" do Google.
AFD
3
ViewModelProviders.of () foi descontinuado. Você pode passar um Fragment ou FragmentActivity para o novo construtor ViewModelProvider (ViewModelStoreOwner) para obter a mesma funcionalidade. (aosp / 1009889)
Raghu Krishnan R
31
Equivalente a Java:YourViewModel viewModel = new ViewModelProvider(this).get(YourViewModel.class);
ban-geoengineering
16
Preocupa-me se algum dia o Google descontinuar o uso TextViewou EditTextintroduzir um novo componente.
Pranjal Choladhara 18/11/19
4
O androidx lifecycle-viewmodel 2.1.0 não possui um construtor sem uma fábrica. usar simplesmente (isto) não funciona. ViewModelProvider (ViewModelStoreOwner, Factory) e ViewModelProvider (ViewModelStore, Factory) são os únicos construtores
DevinM
70

Como o @FantasyFang mencionado em sua resposta, use a versão mais recente para a lifecycle:lifecycle-extensionsque neste momento é 2.2.0-alpha03. Portanto, você deve adicionar no seu arquivo build.gradle a seguinte linha:

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

Para quem está usando Java, para resolver isso, passe esses argumentos diretamente para o construtor do ViewModelProvider :

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

Ou, se você não usa uma fábrica, basta usar:

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

Sem passar seu objeto de fábrica.

Alex Mamo
fonte
1
Você deve usar o seguinte em build.gradle: implementação "androidx.lifecycle: lifecycle-viewmodel: $ lifecycle_version" Conforme observado em developer.android.com/jetpack/androidx/releases/lifecycle As APIs nas extensões de ciclo de vida foram descontinuadas. Em vez disso, inclua dependências para os artefatos específicos do Ciclo de Vida que você precisa.
Kenneth Argo
40

A partir de 2.2.0. as extensões do ciclo de vida foram descontinuadas. Consulte a documentação do Google .

Este é o recorte da página:

As APIs nas extensões do ciclo de vida foram descontinuadas. Em vez disso, inclua dependências para os artefatos específicos do Ciclo de Vida que você precisa.

As novas bibliotecas são:

// 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}"

O novo código para JAVA:

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

Ou para Kotlin:

viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
Kenneth Argo
fonte
Mantemos a importância do ViewModelProvider ou precisamos recriá-lo novamente; nesse caso, todas as instâncias subjacentes também serão destruídas. Eu não sei o motivo de recriá-lo, se a idéia é observar o ciclo de vida do fragmento / atividade
TheRealChx101
31

Descontinuado de: ViewModelProviders.of(this, provider).get(VM::class.java)

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

Braian Coronel
fonte
4
Exatamente o que eu estava procurando.
Rahul Bali
21

No início de 2020, o Google descontinuou a classe ViewModelProviders , na versão 2.2.0 da biblioteca do ciclo de vida do androidx.

Não é mais necessário usar o ViewModelProviders para criar uma instância de um ViewModel; você pode passar sua instância de Fragment ou Activity para o construtor ViewModelProvider.

Se você usar o código como:

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

você receberá um aviso de que o ViewModelProviders foi preterido.

Para evitar o uso de bibliotecas obsoletas, faça as seguintes alterações:

  1. No arquivo build.gradle (Module: app), use a versão 2.2.0 dos componentes do ciclo de vida:

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

    Se você deseja usar o ViewModel de um fragmento, use

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

    fragment-ktx inclui automaticamente activity-ktx, assim você não precisa especificar ambos nas dependências.

  2. Você precisa especificar o Java 8 na seção android:

    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. Em seu Fragmento ou Atividade, altere a importação para:

    import androidx.activity.viewModels

  4. O código para criar um ViewModel se torna:

    val viewModel: CalculatorViewModel by viewModels()

    ao invés de

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

    Use o objeto viewModel como:

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

    Onde newNumer é um objeto LiveData

    Em um fragmento que você deseja compartilhar o ViewModel da atividade, você usaria

    val viewModel: CalculatorViewModel by activityViewModels()

É o equivalente a passar a instância Activity na função (descontinuada) ViewModelProviders.of().

kgandroid
fonte
17

ViewModelProviders.of () foi descontinuado. insira a descrição da imagem aqui

Use os construtores ViewModelProvider diretamente, pois agora eles manipulam a função padrão ViewModelProvider.Factory.

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

Sim @Tarek, está obsoleto. Use agora com AndroidX:

val yourViewModel = ViewModelProvider.NewInstanceFactory().create(YourVideoModel::class.java)
Paulo Linhares - Packapps
fonte
5
Esta resposta está errada. Você deve estar usando uma ViewModelProvider(viewModelStoreOwner, factory).get(YourVideoModel::class.java)outra forma a sua onCleared()vontade não funcionar corretamente, e ViewModel não será mantido em toda mudança de configuração. Não use esta resposta.
EpicPandaForce
13

Provavelmente você pode apenas usar:

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

sem precisar adicionar android.arch.lifecycle:extensions:1.1.1como dependência.

xiaoyu
fonte
8

Estou usando android Xe também tive esse problema.

Primeiro de tudo , você deve adicionar essas dependências ao seu Gradle:

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

No meu caso, a $ lifecycle_version foi 2.2.0-rc02

Segundo: a importação para o ViewModelProviderdeve ser:

import androidx.lifecycle.ViewModelProvider

Você pode inicializar seu vIewModel como os exemplos abaixo:

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

val viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
Igor Fridman
fonte
obrigado por sua resposta, mas quando eu o uso, o viewmodel observe e a vinculação de dados de campos não funciona mais
Mosa
Eu acredito que androidx.lifecycle:lifecycle-compileré obsoleto por androidx.lifecycle:lifecycle-common-java8.
Bink
8

Na verdade, o que o ViewModelProviders.of()método faz sob o capô?

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

Toma Fragmentcomo argumento, cria um ViewModelProviderobjeto e passa o fragmento diretamente ao ViewModelProviderconstrutor.

Nós podemos usar da mesma maneira também.

Por exemplo, antes:

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

Depois de:

OurViewModel mOurViewModel = new ViewModelProvider(this).get(OurViewModel.class);
Hayk Mkrtchyan
fonte
Se você implementa um Factory, você tem outra maneira: ViewModelProviderpossui um construtor que espera a ViewModelStoreOwnere a Factory.
russellhoff
3

Não sou especialista, mas tenho uma linha de código que resolveu meu problema em Java. Espero que isso ajude alguém.

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

Como eu disse, gostaria de fornecer mais detalhes, mas isso corrigiu esse problema para mim.

ZeePee
fonte
Este código está errado, onCleared()não será chamado dessa maneira e seu ViewModel será recriado a cada vez (não mantido para alterações na configuração).
EpicPandaForce
Você pode explicar um pouco mais com um certo exemplo, o que consertaria meu erro? Por favor, cole uma referência à explicação ou a qualquer coisa que torne as coisas mais claras
ZeePee
viewModel = new ViewModelProvider(this).get(MyViewModel.class). Se você AndroidViewModelnão obtiver a Application, então há uma incompatibilidade de versão entre o Ciclo de vida e a Atividade / Fragmento.
EpicPandaForce
Ok, chamar getApplicationContext está errado? Deveria ser apenas getContext?
ZeePee
1
O problema está criando um em new ViewModelProvider.AndroidViewModelFactory(vez de um new ViewModelProvider(.
EpicPandaForce
3

Usa isto:

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

Você pode usar isso:

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

"this" entre parênteses é o proprietário da instância YourViewModel.

Amin
fonte
1

Esta resposta é para Java, mas você pode entender o ponto principal. A solução é que você precisa usar o ViewModelProvider porque o ViewModelProviders foi preterido :

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

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

Exemplo de uso é:

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

Além disso, não se esqueça de atualizar as Dependências do Gradle : verifique aqui as últimas versões delas

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

!!! No entanto, tenha cuidado, pois algumas respostas recomendam esta solução, mas ela não funcionou para mim:

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

Porque quando usei dessa maneira, cheguei abaixo da Mensagem de erro:

Causado por: java.lang.RuntimeException: Não é possível criar uma instância da classe com.canerkaseler.mvvmexample.ViewModel

@canerkaseler

canerkaseler
fonte
Esta resposta está errada. Você precisa passar a fábrica para um ViewModelProvider. Se você chamar diretamente create, onCleared()não funcionará corretamente.
EpicPandaForce
De fato, você literalmente disse apenas para não usar a resposta correta. Parece que você teve uma incompatibilidade entre você androidx.coree suas androidx.lifecycledependências.
EpicPandaForce
Normalmente eu escrevi a fábrica para o ViewModelProvider. No entanto, você o excluiu. ContactViewModel contactViewModel = new ViewModelProvider.AndroidViewModelFactory (getApplication ()). Create (ContactViewModel.class); Por que você excluiu na minha resposta? Você passou códigos errados.
canerkaseler
0

Quando você usa punhal, você passará a fábrica no construtor

  MobileViewModel mobileViewModel = new ViewModelProvider(this,providerFactory).get(MobileViewModel.class);
Apoorv Vardhman
fonte
-2

Se você tem essa implementação

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

Tente usar viewModel = MainViewModel()

Eddy Yoel Fresno Hernández
fonte
Esta não é uma maneira de instanciar um modelo de exibição. Você deve usar a classe ViewModelProvider para isso
Emmanuel Mtali
-2

Tente isso ...

 LocationViewModel locationViewModel = new ViewModelProvider(this).get(LocationViewModel.class);
Shrawan
fonte
-5

deve funcionar dessa maneira

 viewModel = ViewModelProviders.of(this@MainActivity).get(MainActivityViewModel::class.java)
Hamdi Hanbali
fonte
1
Embora seu código instale a classe is, não criará a conexão com o estado de exibição necessário para que a classe View Model responda corretamente aos eventos do ciclo de vida. Você precisa visualizar os modelos da maneira correta para que eles respondam e honrem os ciclos de vida de seus pais, caso contrário, eles serão recriados sempre em branco.
Kenneth Argo
Conforme observado acima pelo OP e outros; a classe ViewModelProviders foi preterida. Veja: developer.android.com/reference/androidx/lifecycle/…
Kenneth Argo