ViewModelProviders เลิกใช้แล้วใน 1.1.0


171

มองไปที่เอกสารของ GoogleสำหรับViewModelพวกเขาแสดงให้เห็นด้านล่างโค้ดตัวอย่างเกี่ยวกับวิธีการที่จะได้รับViewModel:

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

เมื่อใช้การพึ่งพาล่าสุดไม่มีระดับดังกล่าวandroid.arch.lifecycle:extensions:1.1.1ViewModelProviders

ไปที่เอกสารสำหรับViewModelProvidersฉันเห็นความคิดเห็นว่า:

คลาสนี้เลิกใช้แล้วในระดับ API 1.1.0 ใช้ ViewModelProvider.AndroidViewModelFactory

ปัญหาคือเมื่อพยายามใช้ViewModelProvider.AndroidViewModelFactoryไม่พบofวิธีการที่เทียบเท่าเพื่อรับอินสแตนซ์ของไฟล์ViewModel.

สิ่งที่ฉันพยายามทำ:

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

ดังนั้นชื่อของเมธอดcreateฉันจึงได้รับอินสแตนซ์ใหม่ของ ViewModel ทุกครั้งที่เรียกมันซึ่งไม่ใช่สิ่งที่ฉันเป็น

มีความคิดใดบ้างที่จะแทนที่โค้ดที่เลิกใช้งานด้านบน


ใช้รูปแบบซิงเกิลตันหรือเปลี่ยนเป็น AndroidX
Oussema Aroua

คำตอบ:


38

อัปเดต 2020-06-16 : ปัจจุบัน ViewModelProvidersเลิกใช้งานแล้วและไม่ควรใช้อีกต่อไป คำถามและคำตอบนี้มาจากปลายปี 2018 เมื่อไม่เป็นเช่นนั้น คำถามและคำตอบนี้ใช้สำหรับ Architecture Components รุ่นเก่าViewModelProvidersไม่ใช่ AndroidX edition


เมื่อใช้การพึ่งพาล่าสุดไม่มีระดับดังกล่าวandroid.arch.lifecycle:extensions:1.1.1ViewModelProviders

ใช่มี. เพื่อสาธิตสิ่งนี้:

  • สร้างโปรเจ็กต์ใหม่ใน Android Studio 3.2.1 (ด้วย Kotlin, minSdkVersion21, เทมเพลต "กิจกรรมว่าง")

  • เพิ่ม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 1.1.0 ใช้ ViewModelProvider.AndroidViewModelFactory

ความคิดเห็นนั้นอยู่ใต้ViewModelProviders.DefaultFactoryรายการคลาสและอ้างถึงคลาสนั้นไม่ใช่ViewModelProviders:

ภาพหน้าจอของเอกสาร

มีความคิดใดบ้างที่จะแทนที่โค้ดที่เลิกใช้งานด้านบน

ใช้ViewModelProviders.


1
@TareKKhoury: นั่นจะอธิบายได้! การติดตามว่าโมดูลใดต้องการการอ้างอิงที่แน่นอนอาจเป็นเรื่องท้าทาย ฉันดีใจที่ทราบว่าคุณใช้งานได้จริง!
CommonsWare

20
สิ่งนี้ไม่เป็นความจริงอีกต่อไปViewModelProviders.of()ไม่มีแล้ว
EpicPandaForce

364

ฉันใช้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: แก้ไขกรณีของผู้รับมอบสิทธิ์


174
ฉันค่อนข้างเบื่อกับวงจร "ค่าเสื่อมราคา" ที่คงที่โดย Google
AFD

3
ViewModelProviders.of () เลิกใช้งานแล้ว คุณสามารถส่ง Fragment หรือ FragmentActivity ไปยังคอนสตรัคเตอร์ ViewModelProvider (ViewModelStoreOwner) ใหม่เพื่อให้ได้ฟังก์ชันเดียวกัน (aosp / 1009889)
Raghu Krishnan R

35
เทียบเท่า Java:YourViewModel viewModel = new ViewModelProvider(this).get(YourViewModel.class);
ban-geoengineering

21
ฉันกังวลว่าสักวัน Google จะเลิกใช้งานTextViewหรือEditTextและแนะนำคอมโพเนนต์ใหม่
Pranjal Choladhara

4
androidx lifecycle-viewmodel 2.1.0 ไม่มีตัวสร้างที่ไม่มีโรงงาน การใช้เพียงแค่ (นี้) ไม่ได้ผล ViewModelProvider (ViewModelStoreOwner, Factory) และ ViewModelProvider (ViewModelStore, Factory) เป็นผู้สร้างเท่านั้น
DevinM

76

ในฐานะที่เป็น @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: การใช้งาน "androidx.lifecycle: lifecycle-viewmodel: $ lifecycle_version" ตามที่ระบุไว้ในdeveloper.android.com/jetpack/androidx/releases/lifecycle API ใน Lifecycle-extensions เลิกใช้งานแล้ว ให้เพิ่มการอ้างอิงสำหรับสิ่งประดิษฐ์ Lifecycle เฉพาะที่คุณต้องการแทน
Kenneth Argo

47

ณ 2.2.0. เลิกใช้งานส่วนขยายอายุการใช้งานแล้ว อ้างถึงGoogle เอกสาร

นี่คือภาพที่ตัดมาจากหน้า:

API ในส่วนขยายวงจรการใช้งานเลิกใช้งานแล้ว ให้เพิ่มการอ้างอิงสำหรับสิ่งประดิษฐ์ Lifecycle เฉพาะที่คุณต้องการแทน

ไลบรารีใหม่ ได้แก่ :

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


27

ในช่วงต้นปี 2020 Google ได้เลิกใช้งานคลาส ViewModelProvidersในเวอร์ชัน 2.2.0 ของไลบรารีวงจรการใช้งาน androidx

ไม่จำเป็นต้องใช้ 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"
    

    หากคุณต้องการใช้ ViewModel จาก Fragment แทนให้ใช้

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

    Fragment-ktx จะรวม activity-ktx โดยอัตโนมัติดังนั้นคุณไม่จำเป็นต้องระบุทั้งสองอย่างในการอ้างอิง

  2. คุณต้องระบุ Java 8 ในส่วน 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. ในส่วนย่อยหรือกิจกรรมของคุณเปลี่ยนการนำเข้าเป็น:

    นำเข้า 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

    ใน Fragment ที่คุณต้องการแชร์ ViewModel ของกิจกรรมคุณจะต้องใช้

    val viewModel: CalculatorViewModel by activityViewModels()
    

นั่นเท่ากับการส่งผ่านอินสแตนซ์กิจกรรมในViewModelProviders.of()ฟังก์ชัน(เลิกใช้แล้ว)


20

ViewModelProviders.of () เลิกใช้งานแล้ว ป้อนคำอธิบายภาพที่นี่

ใช้ตัวสร้าง ViewModelProvider โดยตรงเนื่องจากตอนนี้จัดการกับบทบาท ViewModelProvider.Factory เริ่มต้น

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

15

คุณสามารถใช้:

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

โดยไม่จำเป็นต้องเพิ่มandroid.arch.lifecycle:extensions:1.1.1เป็นการอ้างอิง


14

ใช่ @Tarek เลิกใช้งานแล้ว ใช้ตอนนี้กับ AndroidX:

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

11
คำตอบนี้ผิด คุณควรใช้ViewModelProvider(viewModelStoreOwner, factory).get(YourVideoModel::class.java)มิฉะนั้นonCleared()จะทำงานไม่ถูกต้องและ ViewModel จะไม่ถูกเก็บไว้ในการเปลี่ยนแปลงการกำหนดค่า อย่าใช้คำตอบนี้
EpicPandaForce


12

จริงๆแล้ว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มีตัวสร้างซึ่งคาดหวังทั้ง a ViewModelStoreOwnerและFactory.
russellhoff

9

ฉันใช้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)

ขอบคุณสำหรับคำตอบของคุณ แต่เมื่อฉันใช้มันแล้ว viewmodel จะสังเกตและฟิลด์ databinding ไม่ทำงานอีกต่อไป
Mosa

ผมเชื่อว่าไม่มีจำหน่ายแล้วโดยandroidx.lifecycle:lifecycle-compiler androidx.lifecycle:lifecycle-common-java8
Bink

6

ใช้สิ่งนี้:

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

ตามที่ชาวแมนดาโลเรียนจะกล่าวว่า:This is the Way!
Starwave


4

คุณสามารถใช้สิ่งนี้แทน:

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

"this" ในวงเล็บคือเจ้าของอินสแตนซ์ YourViewModel


3

ฉันไม่ใช่ผู้เชี่ยวชาญ แต่ฉันมีโค้ดหลายบรรทัดที่แก้ปัญหาของฉันใน Java หวังว่านี่จะช่วยใครบางคนได้

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

อย่างที่ฉันบอกว่าฉันชอบที่จะให้รายละเอียดเพิ่มเติม แต่สิ่งนี้ช่วยแก้ปัญหานี้ให้ฉันได้


รหัสนี้ไม่ถูกต้องonCleared()จะไม่ถูกเรียกด้วยวิธีนี้และ ViewModel ของคุณจะถูกสร้างขึ้นใหม่ทุกครั้ง (ไม่ได้เก็บไว้สำหรับการเปลี่ยนแปลง config)
EpicPandaForce

ช่วยอธิบายเพิ่มเติมอีกเล็กน้อยได้ไหมว่าอะไรจะแก้ไขข้อผิดพลาดของฉันได้ กรุณาวางการอ้างอิงถึงคำอธิบายหรือสิ่งใด ๆ ที่จะทำให้สิ่งต่างๆชัดเจนขึ้น
ZeePee

viewModel = new ViewModelProvider(this).get(MyViewModel.class). หากคุณAndroidViewModelไม่ได้รับแสดงApplicationว่าคุณมีเวอร์ชันที่ไม่ตรงกันระหว่าง Lifecycle และ Activity / Fragment
EpicPandaForce

ตกลงเรียก getApplicationContext ผิดหรือเปล่า ควรเป็น getContext หรือไม่?
ZeePee

1
ปัญหาคือการสร้างnew ViewModelProvider.AndroidViewModelFactory(แทนไฟล์new ViewModelProvider(.
EpicPandaForce

1

เมื่อคุณใช้กริชคุณจะผ่านโรงงานในคอนสตรัคเตอร์

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

1

คำตอบนี้ใช้สำหรับ 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 Dependencies : ตรวจสอบเวอร์ชันล่าสุดที่นี่

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

!!! อย่างไรก็ตามโปรดใช้ความระมัดระวังเนื่องจากบางคำตอบแนะนำวิธีแก้ปัญหานี้ แต่ไม่ได้ผลสำหรับฉัน:

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

เพราะเมื่อฉันใช้วิธีนี้ฉันได้รับข้อความแสดงข้อผิดพลาดด้านล่าง:

เกิดจาก: java.lang.RuntimeException: ไม่สามารถสร้างอินสแตนซ์ของคลาส com.canerkaseler.mvvmexample.ViewModel

@canerkaseler


คำตอบนี้ผิด คุณต้องส่งโรงงานไปยัง ViewModelProvider หากคุณเรียกโดยตรงcreateก็onCleared()จะทำงานไม่ถูกต้อง
EpicPandaForce

อันที่จริงคุณแค่บอกว่าไม่ได้ใช้คำตอบที่ถูกต้อง เสียงเหมือนคุณมีไม่ตรงกันระหว่างคุณandroidx.coreและคนที่คุณandroidx.lifecycleอ้างอิง
EpicPandaForce

ปกติผมเขียนโรงงานไว้ที่ ViewModelProvider อย่างไรก็ตามคุณลบมัน ContactViewModel contactViewModel = ViewModelProvider ใหม่ AndroidViewModelFactory (getApplication ()) สร้าง (ContactViewModel.class); ทำไมคุณถึงลบคำตอบของฉัน คุณส่งรหัสผิด
canerkaseler

0

ในกรณีที่คุณดูวิดีโอจากUdacityที่ที่คุณสร้างGameViewModelและคุณไม่ต้องการเขียนโค้ดที่เลิกใช้งานเพียงแค่แทนที่:

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

ด้วยรหัสต่อไปนี้:

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

แล้วกลับไปอ่าน ASAP !!



-2

หากคุณมีการใช้งานนี้

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

ลองนำไปใช้ viewModel = MainViewModel()


นี่ไม่ใช่วิธีในการสร้างอินสแตนซ์โมเดลมุมมอง คุณต้องใช้คลาส ViewModelProvider สำหรับสิ่งนั้น
Emmanuel Mtali

-5

ควรใช้วิธีนี้

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

1
แม้ว่าโค้ดของคุณจะเป็นตัวอย่าง แต่คลาสจะไม่สร้างการเชื่อมต่อกับสถานะมุมมองที่จำเป็นเพื่อให้คลาส View Model ตอบสนองต่อเหตุการณ์ในวงจรชีวิตได้อย่างถูกต้อง คุณต้องยกตัวอย่างดูโมเดลในลักษณะที่ถูกต้องเพื่อให้พวกเขาตอบสนองและให้เกียรติกับวงจรชีวิตของพ่อแม่ของพวกเขาที่พวกเขาจะถูกสร้างขึ้นใหม่สดและว่างเปล่าทุกครั้ง
Kenneth Argo

ตามที่ระบุไว้ข้างต้นโดย OP และอื่น ๆ ; เลิกใช้คลาส ViewModelProviders แล้ว ดู: developer.android.com/reference/androidx/lifecycle/…
Kenneth Argo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.