Patrząc na dokumenty Google dla ViewModel
, pokazują one poniższy przykładowy kod, jak uzyskać ViewModel
:
val model = ViewModelProviders.of(this).get(MyViewModel::class.java)
W przypadku korzystania z najnowszej zależności android.arch.lifecycle:extensions:1.1.1
nie ma takiej klasy ViewModelProviders
.
Przechodząc do dokumentacji dla ViewModelProviders
, zobaczyłem komentarz mówiący:
Ta klasa została wycofana na poziomie interfejsu API 1.1.0. Użyj ViewModelProvider.AndroidViewModelFactory
Problem polega na tym, że podczas próby użycia ViewModelProvider.AndroidViewModelFactory
nie można znaleźć równoważnej of
metody, aby uzyskać wystąpienie ViewModel
.
Co próbowałem zrobić:
ViewModelProvider.AndroidViewModelFactory.getInstance(application).create(PlayerViewHolder::class.java)
Stąd nazwa metody create
, za każdym razem, gdy ją wywołuję, otrzymuję nowe wystąpienie ViewModel, co nie jest tym, czego szukam.
Jakieś pomysły, co zastąpi przestarzały kod powyżej?
Odpowiedzi:
UPDATE 2020-06-16 : Obecnie
ViewModelProviders
jest przestarzały i nie powinien być już używany. To pytanie i odpowiedź pochodziły z końca 2018 roku, kiedy tak nie było. To pytanie i odpowiedź dotyczą również starszej wersji Architecture ComponentsViewModelProviders
, a nie wersji AndroidX.Tak jest. Aby to zademonstrować:
Utwórz nowy projekt w Android Studio 3.2.1 (z Kotlin,
minSdkVersion
21, szablon „pusta aktywność”)Dodaj
android.arch.lifecycle:extensions:1.1.1
do zależnościapp
modułuTo da ci
app/build.gradle
polubienie: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' }
Zobaczysz wtedy tę bibliotekę w „Bibliotekach zewnętrznych” z tą klasą:
Będziesz mógł odwołać się do tej klasy:
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) } }
Ten komentarz znajduje się pod
ViewModelProviders.DefaultFactory
wpisem do zajęć i odnosi się do tej klasy, a nieViewModelProviders
:Użyj
ViewModelProviders
.źródło
ViewModelProviders.of()
nie istnieje.Używam
2.2.0
wersji z rozszerzeniami cyklu życia :implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
Powinno działać, używając
ViewModelProvider
konstruktora.// With ViewModelFactory val viewModel = ViewModelProvider(this, YourViewModelFactory).get(YourViewModel::class.java) //Without ViewModelFactory val viewModel = ViewModelProvider(this).get(YourViewModel::class.java)
Aktualizacja 2020/5/15
Znajduję inny elegancki sposób na osiągnięcie tego celu, może pomóc Android KTX
implementation "androidx.fragment:fragment-ktx:1.2.4" val viewmodel: MYViewModel by viewModels() val viewmodel: MYViewModel by viewModels { myFactory } //With factory
Odniesienie: https://developer.android.com/reference/kotlin/androidx/fragment/app/package-summary#viewmodels
2020/06/25: poprawiono przypadek delegata
źródło
YourViewModel viewModel = new ViewModelProvider(this).get(YourViewModel.class);
TextView
lubEditText
i wprowadzi nowy składnik.Jak @FantasyFang wspomniał w swojej odpowiedzi, użyj najnowszej wersji,
lifecycle:lifecycle-extensions
która w tej chwili jest2.2.0-alpha03
. Dlatego w pliku build.gradle należy dodać następujący wiersz:implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-alpha03'
Dla tych, którzy używają Javy, aby rozwiązać ten problem, przekaż te argumenty bezpośrednio do konstruktora ViewModelProvider :
MyViewModel viewModel = new ViewModelProvider(this, myViewModelFactory).get(MyViewModel.class);
Lub jeśli nie korzystasz z fabryki, po prostu użyj:
MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);
Bez przekazywania obiektu fabrycznego.
źródło
Od 2.2.0. rozszerzenia cyklu życia zostały wycofane. Zapoznaj się z dokumentacją Google .
To jest wycięcie ze strony:
Nowe biblioteki to:
// 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}"
Nowy kod dla JAVA:
viewModel = new ViewModelProvider(this).get(MyViewModel.class);
Lub dla Kotlina:
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
źródło
Wycofane z:
ViewModelProviders.of(this, provider).get(VM::class.java)
Do:
ViewModelProvider(this, provider).get(VM::class.java)
źródło
Na początku 2020 roku firma Google wycofała klasę ViewModelProviders w wersji 2.2.0 biblioteki cyklu życia systemu Androidx.
Nie jest już konieczne używanie ViewModelProviders do tworzenia wystąpienia ViewModel, zamiast tego można przekazać wystąpienie Fragment lub Activity do konstruktora ViewModelProvider.
Jeśli używasz kodu takiego jak:
val viewModel = ViewModelProviders.of(this).get(CalculatorViewModel::class.java)
pojawi się ostrzeżenie, że ViewModelProviders jest przestarzałe.
Aby uniknąć używania przestarzałych bibliotek, wprowadź następujące zmiany:
W pliku build.gradle (Module: app) użyj wersji 2.2.0 komponentów cyklu życia:
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation "androidx.activity:activity-ktx:1.1.0"
Jeśli chcesz zamiast tego użyć ViewModel z fragmentu, użyj
implementation "androidx.fragment:fragment-ktx:1.2.2"
fragment-ktx automatycznie dołącza aktywność-ktx, więc nie musisz określać obu w zależnościach.
Musisz określić Java 8 w sekcji 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" } }
W swoim fragmencie lub działaniu zmień import na:
import androidx.activity.viewModels
Kod do utworzenia ViewModel staje się wtedy:
val viewModel: CalculatorViewModel by viewModels()
zamiast
val viewModel = ViewModelProviders.of(this).get(CalculatorViewModel::class.java)
Użyj obiektu viewModel jako:
val viewModel: CalculatorViewModel by viewModels() viewModel.newNumber.observe(this, Observer<String> { stringResult -> newNumber.setText(stringResult) })
gdzie newNumer jest obiektem LiveData
W fragmencie, który chcesz udostępnić ViewModel działania, użyjesz
val viewModel: CalculatorViewModel by activityViewModels()
Jest to odpowiednik przekazania wystąpienia Activity w (przestarzałej)
ViewModelProviders.of()
funkcji.źródło
ViewModelProviders.of () został wycofany.
Użyj konstruktorów ViewModelProvider bezpośrednio, ponieważ teraz obsługują one domyślną rolę ViewModelProvider.Factory.
mainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);
źródło
Prawdopodobnie możesz po prostu użyć:
val viewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(MyViewModel::class.java)
bez konieczności dodawania
android.arch.lifecycle:extensions:1.1.1
jako zależności.źródło
Tak @Tarek, jest przestarzały. Użyj teraz z AndroidX:
val yourViewModel = ViewModelProvider.NewInstanceFactory().create(YourVideoModel::class.java)
źródło
ViewModelProvider(viewModelStoreOwner, factory).get(YourVideoModel::class.java)
przeciwnym razie twójonCleared()
nie będzie działał poprawnie, a ViewModel nie zostanie zachowany po zmianie konfiguracji. Nie używaj tej odpowiedzi.Użyj ViewModelProvider bezpośrednio zamiast użytkownika ViewModelProviders.of (), jak wspomniano w dokumentacji.
ViewModelProvider(this).get(XViewModel::class.java)
https://developer.android.com/reference/androidx/lifecycle/ViewModelProviders
źródło
Właściwie, co robi ta
ViewModelProviders.of()
metoda pod maską?@Deprecated @NonNull @MainThread public static ViewModelProvider of(@NonNull Fragment fragment) { return new ViewModelProvider(fragment); }
Przyjmuje
Fragment
jako argument, tworzyViewModelProvider
obiekt i przekazuje fragment bezpośrednio doViewModelProvider
konstruktora.Możemy też użyć tego samego sposobu.
Np. Przed:
OurViewModel mOurViewModel = ViewModelProviders.of(this).get(OurViewModel.class);
Po:
OurViewModel mOurViewModel = new ViewModelProvider(this).get(OurViewModel.class);
źródło
ViewModelProvider
ma konstruktora, który oczekuje zarówno a, jakViewModelStoreOwner
i aFactory
.Używam
android X
i też miałem ten problem.Przede wszystkim powinieneś dodać te zależności do
Gradle
:implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
W moim przypadku $ lifecycle_version to
2.2.0-rc02
Po drugie: import dla
ViewModelProvider
powinien być:import androidx.lifecycle.ViewModelProvider
Następnie możesz zainicjować swój vIewModel, jak na poniższych przykładach:
val viewModel = ViewModelProvider(this, YourFactoryInstace).get(MainViewModel::class.java) val viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
źródło
androidx.lifecycle:lifecycle-compiler
jest przestarzałyandroidx.lifecycle:lifecycle-common-java8
.Użyj tego:
YourViewModel yourViewModel = new ViewModelProvider.AndroidViewModelFactory(getApplication()).create(YourViewModel.class);
źródło
This is the Way!
Jeśli używasz Kotlin, możesz użyć delegata właściwości w
viewModels()
następujący sposób:val viewModel: YourViewModel by viewModels()
Źródło: https://forums.bignerdranch.com/t/solution-to-deprecated-method-viewmodelproviders-of/16833
źródło
Możesz użyć tego zamiast:
viewModel= ViewModelProvider(this).get(YourViewModel::class.java)
„this” w nawiasach oznacza właściciela instancji YourViewModel.
źródło
Nie jestem ekspertem, ale mam wiersz kodu, który rozwiązał mój problem w Javie. Mam nadzieję, że to komuś pomoże.
viewModel = new ViewModelProvider .AndroidViewModelFactory(getApplication()) .create(ViewModel.class);
Jak powiedziałem, chciałbym podać więcej szczegółów, ale to rozwiązało ten problem.
źródło
onCleared()
nie zostanie nazwany w ten sposób, a Twój ViewModel zostanie odtworzony za każdym razem (nie będzie zachowany w przypadku zmian konfiguracji).viewModel = new ViewModelProvider(this).get(MyViewModel.class)
. JeśliAndroidViewModel
nie dostanieszApplication
, oznacza to niezgodność wersji między cyklem życia a działaniem / fragmentem.new ViewModelProvider.AndroidViewModelFactory(
zamiast plikunew ViewModelProvider(
.Kiedy użyjesz sztyletu, przejdziesz przez fabrykę w konstruktorze
MobileViewModel mobileViewModel = new ViewModelProvider(this,providerFactory).get(MobileViewModel.class);
źródło
Ta odpowiedź dotyczy Javy, ale możesz zrozumieć główny punkt. Rozwiązanie polega na tym, że musisz użyć ViewModelProvider, ponieważ ViewModelProviders jest przestarzałe :
//Do not forget import it. import androidx.lifecycle.AndroidViewModel; ViewModelProvider.AndroidViewModelFactory(getApplication()).create(YourViewModel.class);
Przykładowe użycie to:
YourViewModel yourViewModel = new ViewModelProvider.AndroidViewModelFactory(getApplication()).create(YourViewModel.class);
Nie zapomnij także zaktualizować Zależności Gradle : Sprawdź tutaj, czy są ich ostatnie wersje
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.2.0' annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.2.0'
!!! Uważaj jednak, ponieważ niektóre odpowiedzi zalecają to rozwiązanie, ale u mnie nie zadziałało:
yourViewModel = new ViewModelProvider(this).get(YourViewModel.class);
Ponieważ kiedy korzystałem w ten sposób, otrzymałem poniżej komunikat o błędzie:
@canerkaseler
źródło
create
,onCleared()
nie będzie działać poprawnie.androidx.core
i twoimiandroidx.lifecycle
zależnościami.Jeśli oglądasz wideo z
Udacity
miejsca, w którym tworzysz,GameViewModel
a nie chcesz pisać przestarzałego kodu, po prostu zastąp:viewModel = ViewModelProviders.of(this).get(GameViewModel::class.java)
z następującym kodem:
viewModel = ViewModelProvider(this).get(GameViewModel::class.java)
i wróć do czytania jak najszybciej!
źródło
Spróbuj tego...
LocationViewModel locationViewModel = new ViewModelProvider(this).get(LocationViewModel.class);
źródło
Jeśli masz tę implementację
'implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
Spróbuj użyć
viewModel = MainViewModel()
źródło
to powinno działać w ten sposób
viewModel = ViewModelProviders.of(this@MainActivity).get(MainActivityViewModel::class.java)
źródło