ViewModelProviders sudah usang dalam 1.1.0

148

Melihat pada Google docs untuk ViewModel, mereka menunjukkan kode contoh di bawah ini tentang cara mendapatkan ViewModel:

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

Saat menggunakan dependensi terbaru android.arch.lifecycle:extensions:1.1.1tidak ada kelas seperti itu ViewModelProviders.

Pergi ke dokumentasi untuk ViewModelProviders, saya melihat komentar yang mengatakan:

Kelas ini sudah tidak digunakan lagi di API level 1.1.0. Gunakan ViewModelProvider.AndroidViewModelFactory

Masalahnya adalah, ketika mencoba menggunakan ViewModelProvider.AndroidViewModelFactory, tidak dapat menemukan ofmetode yang setara untuk mendapatkan contoh dari ViewModel.

Apa yang saya coba lakukan:

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

Karena itulah nama metode create, saya mendapatkan contoh baru dari ViewModel setiap kali saya menyebutnya, yang bukan apa yang saya cari.

Adakah yang dimaksud dengan penggantian kode usang di atas?

TareK Khoury
sumber
gunakan pola singleton atau ubah ke AndroidX
Oussema Aroua

Jawaban:

31

UPDATE 2020-06-16 : Saat ViewModelProviders ini sudah usang dan seharusnya tidak lagi digunakan. Pertanyaan dan jawaban ini berasal dari akhir 2018, padahal bukan itu masalahnya. Pertanyaan dan jawaban ini juga untuk edisi Komponen Arsitektur yang lebih lama ViewModelProviders, bukan edisi AndroidX.


Saat menggunakan dependensi terbaru android.arch.lifecycle:extensions:1.1.1tidak ada kelas seperti itu ViewModelProviders.

Ya ada. Untuk menunjukkan ini:

  • Buat proyek baru di Android Studio 3.2.1 (dengan minSdkVersiontemplate Kotlin, 21, "aktivitas kosong")

  • Tambahkan android.arch.lifecycle:extensions:1.1.1ke dependensi appmodul

Ini akan memberi Anda app/build.gradlesuka:

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

Anda kemudian akan melihat perpustakaan itu muncul di "Perpustakaan Eksternal" dengan kelas itu:

Perpustakaan Eksternal

Dan Anda akan dapat merujuk kelas itu:

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

Pergi ke dokumentasi untuk ViewModelProviders, saya melihat komentar yang mengatakan: Kelas ini sudah usang di API level 1.1.0. Gunakan ViewModelProvider.AndroidViewModelFactory

Komentar itu ada di bawah ViewModelProviders.DefaultFactoryentri kelas dan merujuk ke kelas itu, bukan ViewModelProviders:

Tangkapan Layar Dokumentasi

Adakah yang dimaksud dengan penggantian kode usang di atas?

Gunakan ViewModelProviders.

CommonsWare
sumber
1
@TareKKhoury: Itu akan menjelaskannya! Melacak modul mana yang membutuhkan dependensi mana yang pasti bisa menjadi tantangan. Saya senang mendengar Anda berhasil!
CommonsWare
13
Ini tidak benar lagi, ViewModelProviders.of()tidak ada lagi.
EpicPandaForce
323

Saya menggunakan 2.2.0versi siklus hidup :

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

Itu harus bekerja, menggunakan ViewModelProviderkonstruktor.

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


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

Pembaruan 2020/5/15

Saya menemukan cara elegan lain untuk mencapai, Android KTX dapat membantu

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: mengoreksi kasus delegasi

Fantasi Fang
sumber
160
Saya agak muak dengan siklus "penyusutan" yang konstan oleh Google.
AFD
3
ViewModelProviders.of () telah ditinggalkan. Anda bisa meneruskan sebuah Fragmen atau FragmentActivity ke konstruktor ViewModelProvider (ViewModelStoreOwner) yang baru untuk mencapai fungsionalitas yang sama. (aosp / 1009889)
Raghu Krishnan R
31
Setara dengan Jawa:YourViewModel viewModel = new ViewModelProvider(this).get(YourViewModel.class);
larangan geoengineering
16
Saya khawatir jika suatu hari Google akan mencela TextViewatau EditTextmemperkenalkan Komponen baru.
Pranjal Choladhara
4
androidx lifecycle-viewmodel 2.1.0 tidak memiliki konstruktor tanpa pabrik. hanya menggunakan (ini) tidak berfungsi. ViewModelProvider (ViewModelStoreOwner, Factory) dan ViewModelProvider (ViewModelStore, Factory) adalah satu-satunya konstruktor
DevinM
70

Seperti @FantasyFang disebutkan dalam jawabannya, gunakan versi terbaru untuk lifecycle:lifecycle-extensionssaat ini 2.2.0-alpha03. Jadi, Anda harus menambahkan file build.gradle pada baris berikut:

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

Bagi mereka yang menggunakan Java, untuk menyelesaikan ini, kirimkan argumen tersebut langsung ke konstruktor ViewModelProvider :

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

Atau jika Anda tidak menggunakan pabrik, cukup gunakan:

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

Tanpa melewati objek pabrik Anda.

Alex Mamo
sumber
1
Anda harus menggunakan yang berikut ini di build.gradle: implementasi "androidx.lifecycle: lifecycle-viewmodel: $ lifecycle_version" Seperti disebutkan dalam developer.android.com/jetpack/androidx/releases/lifecycle API dalam siklus hidup-ekstensi telah ditinggalkan. Sebaliknya, tambahkan dependensi untuk artefak Siklus Hidup spesifik yang Anda butuhkan.
Kenneth Argo
40

Pada 2.2.0. ekstensi siklus hidup telah ditinggalkan. Rujuk ke Dokumentasi Google .

Ini adalah potongan dari halaman:

API dalam ekstensi siklus hidup telah ditinggalkan. Sebaliknya, tambahkan dependensi untuk artefak Siklus Hidup spesifik yang Anda butuhkan.

Perpustakaan baru adalah:

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

Kode baru untuk JAWA:

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

Atau untuk Kotlin:

viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
Kenneth Argo
sumber
Apakah kita menjaga isntsance ViewModelProvider atau harus membuatnya kembali, dalam hal ini, semua instance yang mendasarinya juga akan dihancurkan. Saya tidak punya alasan untuk membuatnya kembali jika idenya adalah untuk menonton siklus hidup fragmen / aktivitas
TheRealChx101
31

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

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

Braian Coronel
sumber
4
persis apa yang saya cari.
Rahul Bali
21

Awal tahun 2020, Google telah mencabut kelas ViewModelProviders , dalam versi 2.2.0 dari perpustakaan siklus hidup androidx.

Tidak perlu lagi menggunakan ViewModelProviders untuk membuat instance dari ViewModel, Anda bisa meneruskan instance Fragment atau Activity Anda ke konstruktor ViewModelProvider sebagai gantinya.

Jika Anda menggunakan kode seperti:

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

Anda akan mendapat peringatan itu ViewModelProviders telah ditinggalkan.

Untuk menghindari penggunaan perpustakaan yang sudah tidak digunakan lagi, buat perubahan berikut:

  1. Dalam file build.gradle (Module: app), gunakan versi 2.2.0 dari komponen siklus hidup:

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

    Jika Anda ingin menggunakan ViewModel sebagai gantinya, gunakan

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

    fragment-ktx secara otomatis menyertakan activity-ktx, jadi Anda tidak perlu menentukan keduanya dalam dependensi.

  2. Anda perlu menentukan Java 8 di bagian 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. Di Fragmen atau Aktivitas Anda, ubah impor ke:

    impor androidx.activity.viewModels

  4. Kode untuk membuat ViewModel kemudian menjadi:

    val viewModel: CalculatorViewModel by viewModels()

    dari pada

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

    Gunakan objek viewModel sebagai:

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

    di mana newNumer adalah objek LiveData

    Dalam Fragmen yang ingin Anda bagikan dengan ViewModel Kegiatan, Anda akan menggunakannya

    val viewModel: CalculatorViewModel by activityViewModels()

Itu sama dengan melewatkan instance Activity dalam fungsi (usang) ViewModelProviders.of().

kgandroid
sumber
17

ViewModelProviders.of () telah ditinggalkan. masukkan deskripsi gambar di sini

Gunakan konstruktor ViewModelProvider secara langsung karena mereka sekarang menangani peran ViewModelProvider.Factory default.

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

Ya @ Tarek, sudah usang. Gunakan sekarang dengan AndroidX:

val yourViewModel = ViewModelProvider.NewInstanceFactory().create(YourVideoModel::class.java)
Paulo Linhares - Packapps
sumber
5
Jawaban ini salah. Anda harus menggunakan yang ViewModelProvider(viewModelStoreOwner, factory).get(YourVideoModel::class.java)sebaliknya Anda onCleared()tidak akan bekerja dengan benar, dan ViewModel tidak akan disimpan di perubahan konfigurasi. Jangan gunakan jawaban ini.
EpicPandaForce
13

Mungkin Anda bisa menggunakan:

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

tanpa perlu menambahkan android.arch.lifecycle:extensions:1.1.1ketergantungan.

Xiaoyu
sumber
8

Saya menggunakan android Xdan juga memiliki masalah ini.

Pertama-tama , Anda harus menambahkan dependensi ini ke Gradle:

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

Dalam kasus saya, $ lifecycle_version adalah 2.2.0-rc02

Kedua: Impor untuk ViewModelProviderharus:

import androidx.lifecycle.ViewModelProvider

Daripada Anda dapat menginisialisasi vIewModel Anda seperti contoh di bawah ini:

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

val viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
Igor Fridman
sumber
terima kasih atas jawaban Anda, tetapi ketika saya menggunakannya maka viewmodel mengamati dan bidang penyatuan data tidak lagi berfungsi
Mosa
Saya percaya androidx.lifecycle:lifecycle-compilersudah usang oleh androidx.lifecycle:lifecycle-common-java8.
Bink
8

Sebenarnya, apa yang dilakukan ViewModelProviders.of()metode di bawah tenda?

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

Dibutuhkan Fragmentsebagai argumen, membuat ViewModelProviderobjek dan meneruskan fragmen langsung keViewModelProvider konstruktor.

Kita juga bisa menggunakan cara yang sama.

Misalnya sebelum:

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

Setelah:

OurViewModel mOurViewModel = new ViewModelProvider(this).get(OurViewModel.class);
Hayk Mkrtchyan
sumber
Jika Anda menerapkan Pabrik, Anda memiliki cara lain: ViewModelProvidermemiliki konstruktor yang mengharapkan a ViewModelStoreOwnerdan a Factory.
russellhoff
3

Saya bukan ahli tetapi saya memiliki garis kode yang memecahkan masalah saya di Jawa. Semoga ini bisa membantu seseorang.

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

Seperti yang saya katakan saya ingin memberikan lebih banyak detail, tetapi ini memperbaiki masalah ini untuk saya.

ZeePee
sumber
Kode ini salah, onCleared()tidak akan dipanggil dengan cara ini dan ViewModel Anda akan dibuat ulang setiap kali (tidak disimpan untuk perubahan konfigurasi).
EpicPandaForce
Bisakah Anda menjelaskan lebih banyak dengan contoh tertentu, apa yang akan memperbaiki kesalahan saya? Tolong, tempel referensi ke penjelasan atau apapun yang akan membuat semuanya lebih jelas
ZeePee
viewModel = new ViewModelProvider(this).get(MyViewModel.class). Jika Anda AndroidViewModeltidak mendapatkan Application, maka Anda memiliki ketidakcocokan versi antara Siklus Hidup dan Aktivitas / Fragmen.
EpicPandaForce
Oke, jadi memanggil getApplicationContext salah? Haruskah itu hanya getContext?
ZeePee
1
Masalahnya adalah menciptakan new ViewModelProvider.AndroidViewModelFactory(bukan new ViewModelProvider(.
EpicPandaForce
3

Gunakan ini:

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

Anda dapat menggunakan ini sebagai gantinya:

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

"this" di dalam tanda kurung adalah pemilik instance YourViewModel.

Amin
sumber
1

Jawaban ini untuk Java tetapi Anda bisa mengerti poin utama. Solusi adalah bahwa Anda perlu menggunakan ViewModelProvider karena ViewModelProviders sudah usang :

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

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

Contoh penggunaan adalah:

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

Juga, jangan lupa perbarui Dependensi Gradle : Periksa di sini untuk versi terakhirnya

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

!!! Namun, berhati-hatilah karena beberapa jawaban merekomendasikan solusi ini tetapi tidak berhasil untuk saya:

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

Karena ketika saya menggunakan cara ini, saya mendapat di bawah Pesan Kesalahan:

Disebabkan oleh: java.lang.RuntimeException: Tidak dapat membuat turunan dari kelas com.canerkaseler.mvvmexample.ViewModel

@canerkaseler

canerkaseler
sumber
Jawaban ini salah. Anda harus melewati pabrik ke ViewModelProvider. Jika Anda secara langsung memohon create, maka onCleared()tidak akan berfungsi dengan benar.
EpicPandaForce
Bahkan, Anda benar-benar hanya mengatakan tidak menggunakan jawaban yang benar. Sepertinya Anda memiliki ketidakcocokan antara Anda androidx.coredan androidx.lifecycledependensi Anda .
EpicPandaForce
Biasanya saya menulis pabrik ke ViewModelProvider. Namun, Anda menghapusnya. ContactViewModel contactViewModel = new ViewModelProvider.AndroidViewModelFactory (getApplication ()). Create (ContactViewModel.class); Mengapa Anda menghapusnya pada jawaban saya? Anda memberikan kode yang salah.
canerkaseler
0

Ketika Anda menggunakan belati maka Anda akan melewati pabrik di konstruktor

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

Jika Anda memiliki implementasi ini

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

Coba gunakan viewModel = MainViewModel()

Eddy Yoel Fresno Hernández
sumber
Ini bukan cara untuk instantiate model tampilan. Anda harus menggunakan kelas ViewModelProvider untuk itu
Emmanuel Mtali
-2

Coba ini...

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

seharusnya bekerja seperti ini

 viewModel = ViewModelProviders.of(this@MainActivity).get(MainActivityViewModel::class.java)
Hamdi Hanbali
sumber
1
Sementara kode Anda akan instance kelas tidak akan membuat koneksi ke negara tampilan yang diperlukan untuk memiliki kelas Model Tampilan untuk merespons dengan benar peristiwa siklus hidup. Anda harus mencantumkan Model Lihat dengan cara yang benar sehingga mereka merespons dan menghormati siklus hidup orang tua mereka, jika tidak mereka akan dibuat ulang dan kosong setiap kali.
Kenneth Argo
Seperti disebutkan di atas oleh OP dan lainnya; kelas ViewModelProviders telah ditinggalkan. Lihat: developer.android.com/reference/androidx/lifecycle/…
Kenneth Argo