ViewModelProviders устарел в 1.1.0

Глядя на Гугл документы для 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 не удается найти эквивалентный метод of для получения экземпляра ViewModel.

Что я пытался сделать:

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

Отсюда и название метода create, я получаю новый экземпляр ViewModel каждый раз, когда вызываю его, а это не то, что мне нужно.

Есть идеи, что такое замена устаревшего кода выше?

использовать одноэлементный шаблон или перейти на AndroidX

Oussema Aroua 23.12.2018 14:01
216
1
109 709
28
Перейти к ответу Данный вопрос помечен как решенный

Ответы 28

это должно работать так

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

В то время как ваш код будет экземпляром класса, он не будет создавать соединение с состоянием представления, которое требуется для того, чтобы класс модели представления правильно реагировал на события жизненного цикла. Вам необходимо правильно создать экземпляры View Models, чтобы они реагировали и соблюдали жизненные циклы своих родителей, иначе они каждый раз воссоздались свежими и пустыми.

Kenneth Argo 04.02.2020 23:35

Как отмечалось выше ОП и другими; класс ViewModelProviders устарел. См .: developer.android.com/reference/androidx/lifecycle/…

Kenneth Argo 04.02.2020 23:50
Ответ принят как подходящий

ОБНОВЛЕНИЕ 2020-06-16: В настоящее времяViewModelProviders устарел и больше не должен использоваться. Этот вопрос и ответ были заданы в конце 2018 года, когда это было не так. Этот вопрос и ответ также относятся к более старой версии компонентов архитектуры ViewModelProviders, а не к версии AndroidX.


When using the latest dependency android.arch.lifecycle:extensions:1.1.1 there is no such class 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)
  }
}

Going to the documentation for ViewModelProviders, I saw a comment saying: This class was deprecated in API level 1.1.0. Use ViewModelProvider.AndroidViewModelFactory

Этот комментарий находится под записью класса ViewModelProviders.DefaultFactory и относится к этому классу, а не к ViewModelProviders:

Documentation Screenshot

Any ideas what is the replacement of deprecated code above?

Используйте ViewModelProviders.

@TareKKhoury: Это все объяснит! Определенно может быть непросто отследить, какие модули и какие зависимости нужны. Рад слышать, что у вас все заработало!

CommonsWare 23.12.2018 14:31

Это уже не так, ViewModelProviders.of() больше не существует.

EpicPandaForce 04.05.2020 08:08

Да @Tarek, он устарел. Используйте сейчас с AndroidX:

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

Это неверный ответ. Вы должны использовать ViewModelProvider(viewModelStoreOwner, factory).get(YourVideoModel::class.java), иначе ваш onCleared() не будет работать правильно, и ViewModel не будет сохраняться при изменении конфигурации. Не используйте этот ответ.

EpicPandaForce 04.05.2020 08:09

Вероятно, вы можете просто использовать:

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

без необходимости добавлять android.arch.lifecycle:extensions:1.1.1 в качестве зависимости.

Я использую версию 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

25.06.2020: исправлен случай делегата

Меня как бы тошнит от постоянного цикла "обесценивания" со стороны Google.

AFD 14.08.2019 15:36

ViewModelProviders.of () устарел. Вы можете передать Fragment или FragmentActivity новому конструктору ViewModelProvider (ViewModelStoreOwner) для достижения той же функциональности. (AOSP / 1009889)

Raghu Krishnan R 19.08.2019 15:11

Эквивалент Java: YourViewModel viewModel = new ViewModelProvider(this).get(YourViewModel.class);

ban-geoengineering 01.10.2019 21:04

Я беспокоюсь, если когда-нибудь Google откажется от поддержки TextView или EditText и представит новый компонент.

Pranjal Choladhara 18.11.2019 10:00

androidx lifecycle-viewmodel 2.1.0 не имеет конструктора без фабрики. использование просто (это) не работает. ViewModelProvider (ViewModelStoreOwner, Factory) и ViewModelProvider (ViewModelStore, Factory) - единственные конструкторы.

DevinM 19.12.2019 18:32

Есть ли причина для изменения?

meh 01.02.2020 20:41

По мере развития программного обеспечения старые реализации устаревают. Это естественно, с этим бороться бесполезно.

A. Steenbergen 10.02.2020 11:32

@AFD правда. Некоторые библиотеки Google меняют API каждый месяц, например WebRTC android. Очень неприятно изучать фреймворк из руководств

Dr Deo 26.03.2020 20:23

Значит, нам нужно каждый раз создавать новые объекты?

TheRealChx101 31.05.2020 17:34

Как отметил @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);

Без передачи вашего фабричного объекта.

Вы должны использовать следующее в build.gradle: implementation "androidx.lifecycle: lifecycle-viewmodel: $ lifecycle_version" Как отмечено в developer.android.com/jetpack/androidx/releases/lifecycle. API в расширениях жизненного цикла устарели. Вместо этого добавьте зависимости для конкретных артефактов жизненного цикла, которые вам нужны.

Kenneth Argo 04.02.2020 23:43

Используйте ViewModelProvider напрямую вместо пользователя ViewModelProviders.of (), как указано в документации.

ViewModelProvider(this).get(XViewModel::class.java)

https://developer.android.com/reference/androidx/lifecycle/ViewModelProviders

ViewModelProviders.of () устарел.

Используйте конструкторы ViewModelProvider напрямую, поскольку они теперь обрабатывают роль ViewModelProvider.Factory по умолчанию.

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

Если вы используете Kotlin, вы можете использовать делегат свойства viewModels() следующим образом:

val viewModel: YourViewModel by viewModels()

Источник: https://forums.bignerdranch.com/t/solution-to-deprecated-method-viewmodelproviders-of/16833

Я использую 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)

спасибо за ваш ответ, но когда я использую его, тогда просмотр модели просмотра и привязка данных к полям больше не работают

Mosa 06.02.2020 11:00

Я считаю, что androidx.lifecycle:lifecycle-compiler устарел androidx.lifecycle:lifecycle-common-java8.

Bink 14.04.2020 23:21

Если у вас есть эта реализация

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

Попробуй использовать viewModel = MainViewModel()

Это не способ создать экземпляр модели представления. Для этого вы должны использовать класс ViewModelProvider

Emmanuel Mtali 12.03.2020 16:31

По состоянию на 2.2.0. расширения жизненного цикла устарели. Обратитесь к Документация Google.

Это вырезка со страницы:

The APIs in lifecycle-extensions have been deprecated. Instead, add dependencies for the specific Lifecycle artifacts you need.

Новые библиотеки:

// 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);

Или для Котлина:

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

Сохраняем ли мы isntsance ViewModelProvider или должны воссоздавать его снова, и в этом случае все базовые экземпляры также будут уничтожены. Я не являюсь причиной его воссоздания, если идея состоит в том, чтобы наблюдать за жизненным циклом фрагмента / активности.

TheRealChx101 31.05.2020 17:35

Спасибо за включение Java - некоторым из нас все еще приходится поддерживать устаревший код.

zkon 17.08.2020 03:41

Я не эксперт, но у меня есть строка кода, которая решила мою проблему на Java. Надеюсь, это кому-то поможет.

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

Как я уже сказал, я хотел бы предоставить более подробную информацию, но это устранило эту проблему для меня.

Этот код неверен, onCleared() не будет называться таким образом, и ваша ViewModel будет воссоздаваться каждый раз (не сохраняется для изменений конфигурации).

EpicPandaForce 04.05.2020 08:08

Не могли бы вы объяснить немного подробнее на конкретном примере, что бы исправить мою ошибку? Пожалуйста, вставьте ссылку на объяснение или что-нибудь, что могло бы прояснить ситуацию

ZeePee 05.05.2020 10:41
viewModel = new ViewModelProvider(this).get(MyViewModel.class). Если ваш AndroidViewModel не получает Application, значит у вас есть несоответствие версий между жизненным циклом и действием / фрагментом.
EpicPandaForce 05.05.2020 11:04

Хорошо, значит, вызов getApplicationContext неверен? Должен ли это быть просто getContext?

ZeePee 05.05.2020 11:18

Проблема заключается в создании new ViewModelProvider.AndroidViewModelFactory( вместо new ViewModelProvider(.

EpicPandaForce 05.05.2020 11:28

Попробуй это...

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

Импортировать

Устарело с:

import androidx.lifecycle.ViewModelProviders;

К:

import androidx.lifecycle.ViewModelProvider;

С использованием

Устарело с:

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

К:

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

именно то, что я искал.

Rahul Bali 30.03.2020 06:04

В начале 2020 года, Google устарел класс ViewModelProviders, в версии 2.2.0 библиотеки жизненного цикла androidx.

Больше нет необходимости использовать ViewModelProviders для создания экземпляра ViewModel, вместо этого вы можете передать свой фрагмент или экземпляр 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"
    

    Если вы хотите вместо этого использовать 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 Activity, вы должны использовать

    val viewModel: CalculatorViewModel by activityViewModels()
    

Это эквивалент передачи экземпляра Activity в (устаревшей) функции ViewModelProviders.of().

Собственно, что делает метод 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 есть конструктор, который ожидает как ViewModelStoreOwner, так и Factory.

russellhoff 11.05.2020 10:47

Вместо этого вы можете использовать это:

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

«this» в круглых скобках - владелец экземпляра YourViewModel.

Это ответ для 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: Проверьте здесь последние их версии

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

!!! Однако будьте осторожны, потому что некоторые ответы рекомендуют это решение, но оно не сработало для меня:

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

Потому что, когда я использовал этот способ, я получил сообщение об ошибке ниже:

Caused by: java.lang.RuntimeException: Cannot create an instance of class com.canerkaseler.mvvmexample.ViewModel

Это неверный ответ. Вам необходимо передать фабрику ViewModelProvider. Если вы вызываете create напрямую, то onCleared() не будет работать правильно.

EpicPandaForce 04.05.2020 08:02

Фактически, вы буквально только что сказали не использовать правильный ответ. Похоже, у вас есть несоответствие между вашими зависимостями androidx.core и androidx.lifecycle.

EpicPandaForce 04.05.2020 08:03

Обычно я записывал фабрику в ViewModelProvider. Однако вы его удалили. ContactViewModel contactViewModel = новый ViewModelProvider.AndroidViewModelFactory (getApplication ()). ‌ create (ContactViewMo‌ del.class); Почему вы удалили его в моем ответе? Вы ввели неправильные коды.

Caner 04.05.2020 13:08

Когда вы используете кинжал, вы передаете factory в конструкторе

  MobileViewModel mobileViewModel = new ViewModelProvider(this,providerFactory).get(MobileViewModel.class);

Использовать это:

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

не будет ли это создавать новый экземпляр каждый раз, когда вызывается create? Предположим, такой жизненный цикл, стоп, onCreate?

Mubashir Murtaza 26.01.2021 07:20

Если вы смотрите видео с Udacity, где вы создаете GameViewModel и не хотите писать устаревший код, просто замените:

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

со следующим кодом:

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

и вернуться к чтению как можно скорее !!

Я продолжал пробовать и закончил с этим решением в Kotlin, вы тоже сможете попробовать его в java.

MainActivity.kt

 val provider : ViewModelProvider = ViewModelProvider(this)
 val VM = provider.get(ViewModelClass::class.java)

build.gradle

implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.0"

Текущая версия библиотек жизненного цикла - 2.3.0 по состоянию на 02.02.2021. См. https://developer.android.com/jetpack/androidx/releases/lifecycle, чтобы проверить текущую версию.

Я столкнулся с той же проблемой. если что-то не работает, попробуйте этот фрагмент кода в своем oncreate и отредактируйте его в соответствии с вашим файлом и бум, вы gtg

val model = ViewModelProvider(viewModelStore,ViewModelProvider.AndroidViewModelFactory.getInstance(application)).get(MainActivityViewModel::class.java)

// вам просто нужно изменить класс модели

Прочтите Как ответить и обновите свой вопрос.

fartem 11.03.2021 05:34

Пользуюсь фабрикой.

ViewModelProvider.AndroidViewModelFactory
            .getInstance(getApplication())
            .create(DashboardViewModel.class);

Просто обновите с

ViewModelProviders.of(this, provider).get(MainActivityViewModel::class.java)

к

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

Вы можете использовать что-то вроде этого:

private  val sharedViewModel: SharedViewModel by viewModels(ownerProducer = { requireActivity() })


ownerProducer = { requireActivity() } // This is only required if you want to share same view model among different fragments.

Я использую библиотеку жизненного цикла 2.3.1 и добавляю ниже зависимость в build.gradle (на уровне модуля)

implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-extensions-ktx:2.2.0'
implementation 'androidx.activity:activity-ktx:1.4.0'
implementation 'androidx.fragment:fragment-ktx:1.3.6'

Объявите viewModels () в своем коде Котлин, как показано ниже:

import androidx.fragment.app.viewModels

private val cartViewModel: CartViewModel by viewModels()

Другие вопросы по теме