ViewModelProviders không được dùng nữa trong 1.1.0


145

Nhìn vào các tài liệu của Google cho ViewModel, họ hiển thị bên dưới mẫu mã trên như thế nào để có được một ViewModel:

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

Khi sử dụng phụ thuộc mới nhất android.arch.lifecycle:extensions:1.1.1không có lớp như vậy ViewModelProviders.

Đi đến tài liệu cho ViewModelProviders, tôi thấy một bình luận nói:

Lớp này không được dùng ở cấp API 1.1.0. Sử dụng ViewModelProvider.AndroidViewModelFactory

Vấn đề là, khi cố gắng sử dụng ViewModelProvider.AndroidViewModelFactory, không thể tìm thấy một ofphương thức tương đương để lấy thể hiện của ViewModel.

Những gì tôi đã cố gắng làm:

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

Do đó, tên của phương thức create, tôi nhận được một phiên bản mới của ViewModel mỗi lần tôi gọi nó, đây không phải là cái mà tôi đang theo đuổi.

Bất kỳ ý tưởng nào là sự thay thế của mã không dùng ở trên?


sử dụng mẫu đơn hoặc thay đổi thành AndroidX
Oussema Aroua

Câu trả lời:


31

CẬP NHẬT 2020-06-16 : Hiện tại ViewModelProviders không được dùng nữa và không còn được sử dụng. Câu hỏi và câu trả lời này là từ cuối năm 2018, khi đó không phải là trường hợp. Câu hỏi và câu trả lời này cũng dành cho phiên bản Cấu trúc Kiến trúc cũ hơn ViewModelProviders, không phải phiên bản AndroidX.


Khi sử dụng phụ thuộc mới nhất android.arch.lifecycle:extensions:1.1.1không có lớp như vậy ViewModelProviders.

Có, có. Để chứng minh điều này:

  • Tạo một dự án mới trong Android Studio 3.2.1 (với mẫu Kotlin, minSdkVersion21, "hoạt động trống")

  • Thêm android.arch.lifecycle:extensions:1.1.1vào các phụ thuộc của appmô-đun

Điều này sẽ cung cấp cho bạn một app/build.gradlenhư:

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

Sau đó, bạn sẽ thấy thư viện đó hiển thị trong "Thư viện bên ngoài" với lớp đó:

Thư viện bên ngoài

Và bạn sẽ có thể tham khảo lớp đó:

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

Đi đến tài liệu cho ViewModelProviders, tôi thấy một bình luận nói rằng: Lớp này không được dùng ở cấp API 1.1.0. Sử dụng ViewModelProvider.AndroidViewModelFactory

Nhận xét đó nằm bên dưới ViewModelProviders.DefaultFactorymục nhập lớp và đề cập đến lớp đó, không phải ViewModelProviders:

Ảnh chụp màn hình tài liệu

Bất kỳ ý tưởng nào là sự thay thế của mã không dùng ở trên?

Sử dụng ViewModelProviders.


1
@TareKKhoury: Điều đó sẽ giải thích điều đó! Theo dõi các mô-đun cần phụ thuộc nào chắc chắn có thể là một thách thức. Tôi rất vui khi biết rằng bạn đã làm cho nó hoạt động!
CommonsWare

12
Điều này không còn đúng nữa, ViewModelProviders.of()không còn tồn tại.
EpicPandaForce

316

Tôi sử dụng 2.2.0phiên bản mở rộng vòng đời :

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

Nó nên được làm việc, sử dụng ViewModelProviderconstructor.

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


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

Cập nhật 2020/5/15

Tôi tìm thấy một cách thanh lịch khác để đạt được, Android KTX có thể giúp

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

Tham chiếu: https://developer.android.com/reference/kotlin/androidx/fragment/app/package-summary#viewmodels

2020/06/25: sửa trường hợp của đại biểu


158
Tôi phát ốm vì chu kỳ "khấu hao" liên tục của Google.
AFD

3
ViewModelProviders.of () đã không được chấp nhận. Bạn có thể chuyển một Fragment hoặc FragmentActivity cho hàm tạo ViewModelProvider (ViewModelStoreOwner) mới để đạt được chức năng tương tự. (aosp / 1009889)
Raghu Krishnan R

31
Tương đương với Java:YourViewModel viewModel = new ViewModelProvider(this).get(YourViewModel.class);
ban-geengineering

16
Tôi lo lắng nếu một ngày nào đó Google sẽ phản đối TextViewhoặc EditTextgiới thiệu Thành phần mới.
Pranjal Choladhara

4
vòng đời androidx-viewmodel 2.1.0 không có hàm tạo mà không có nhà máy. sử dụng đơn giản (điều này) không hoạt động. ViewModelProvider (ViewModelStoreOwner, Factory) và ViewModelProvider (ViewModelStore, Factory) là các nhà xây dựng duy nhất
DevinM

70

Như @FantasyFang đã đề cập trong câu trả lời của anh ấy, hãy sử dụng phiên bản mới nhất cho lifecycle:lifecycle-extensionsthời điểm này 2.2.0-alpha03. Vì vậy, bạn nên thêm vào tập tin build.gradle của mình dòng sau:

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

Đối với những người đang sử dụng Java, để giải quyết việc này, vượt qua những tranh luận trực tiếp đến ViewModelProvider của constructor :

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

Hoặc nếu bạn không sử dụng nhà máy, chỉ cần sử dụng:

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

Không qua đối tượng nhà máy của bạn.


1
Bạn nên sử dụng những điều sau đây trong build.gradle: thực hiện "androidx.lifecycle: vòng đời-viewmodel: $ lifecycle_version" Như đã nêu trong developer.android.com/jetpack/androidx/releases/lifecycle Các API trong vòng đời-phần mở rộng đã được tán thành. Thay vào đó, hãy thêm các phụ thuộc cho các tạo phẩm Vòng đời cụ thể mà bạn cần.
Kenneth Argo

40

Kể từ 2.2.0. các phần mở rộng vòng đời đã không được chấp nhận. Tham khảo Tài liệu Google .

Đây là phần cắt từ trang:

Các API trong phần mở rộng vòng đời đã không được chấp nhận. Thay vào đó, hãy thêm các phụ thuộc cho các tạo phẩm Vòng đời cụ thể mà bạn cần.

Các thư viện mới là:

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

Mã mới cho JAVA:

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

Hoặc cho Kotlin:

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

Chúng tôi có giữ cho ViewModelProvider không hoạt động hay phải tạo lại nó, trong trường hợp đó, tất cả các trường hợp cơ bản cũng sẽ bị hủy. Tôi không có lý do để tạo lại nó nếu ý tưởng là để xem vòng đời của đoạn / hoạt động
TheRealChx101

31

Không dùng nữa: ViewModelProviders.of(this, provider).get(VM::class.java)

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


4
Chính xác những gì tôi đang tìm kiếm.
Raul

20

Đầu năm 2020, Google đã từ chối lớp ViewModelProviders , trong phiên bản 2.2.0 của thư viện vòng đời androidx.

Không còn cần thiết phải sử dụng ViewModelProviders để tạo một phiên bản của ViewModel, bạn có thể chuyển đối tượng Fragment hoặc Activity của mình cho hàm tạo ViewModelProvider.

Nếu bạn sử dụng mã như:

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

bạn sẽ nhận được cảnh báo rằng ViewModelProviders đã không được chấp nhận.

Để tránh sử dụng các thư viện không dùng nữa, hãy thực hiện các thay đổi sau:

  1. Trong tệp build.gradle (Module: ứng dụng), sử dụng phiên bản 2.2.0 của các thành phần vòng đời:

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

    Thay vào đó, nếu bạn muốn sử dụng ViewModel từ một mảnh, hãy sử dụng

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

    Fragment-ktx tự động bao gồm hoạt động-ktx, vì vậy bạn không cần chỉ định cả hai trong phần phụ thuộc.

  2. Bạn cần chỉ định Java 8 trong phần 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. Trong Đoạn hoặc Hoạt động của bạn, thay đổi nhập thành:

    nhập androidx.activity.viewModels

  4. Mã để tạo ViewModel sau đó trở thành:

    val viewModel: CalculatorViewModel by viewModels()

    thay vì

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

    Sử dụng đối tượng viewModel như:

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

    Ở đâu newNumer là một đối tượng LiveData

    Trong một đoạn mà bạn muốn chia sẻ ViewModel của Activity, bạn sẽ sử dụng

    val viewModel: CalculatorViewModel by activityViewModels()

Đó là tương đương với việc truyền đối tượng Activity trong hàm (không dùng nữa) ViewModelProviders.of().


17

ViewModelProviders.of () đã không được chấp nhận. nhập mô tả hình ảnh ở đây

Sử dụng trực tiếp các hàm tạo của ViewModelProvider vì chúng hiện xử lý vai trò ViewModelProvider.Factory mặc định.

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

13

Có @Tarek, nó không được dùng nữa. Sử dụng ngay với AndroidX:

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

5
Câu trả lời này là sai. Bạn nên sử dụng một ViewModelProvider(viewModelStoreOwner, factory).get(YourVideoModel::class.java)cách khác nếu onCleared()không hoạt động chính xác và ViewModel sẽ không được thay đổi cấu hình. Không sử dụng câu trả lời này.
EpicPandaForce

12

Có lẽ bạn chỉ có thể sử dụng:

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

mà không cần thêm android.arch.lifecycle:extensions:1.1.1như phụ thuộc.



8

Tôi đang sử dụng android Xvà cũng có vấn đề này.

Trước hết , bạn nên thêm các phụ thuộc này vào Gradle:

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

Trong trường hợp của tôi, $ lifecycl_version là 2.2.0-rc02

Thứ hai: Việc nhập khẩu ViewModelProviderphải là:

import androidx.lifecycle.ViewModelProvider

Hơn bạn có thể khởi tạo vIewModel của mình như các ví dụ dưới đây:

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

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

cảm ơn câu trả lời của bạn, nhưng khi tôi sử dụng nó thì viewmodel quan sát và cơ sở dữ liệu trường không còn hoạt động
Mosa

Tôi tin androidx.lifecycle:lifecycle-compilerlà bị lỗi thời androidx.lifecycle:lifecycle-common-java8.
Bink

8

Trên thực tế, ViewModelProviders.of()phương pháp làm gì dưới mui xe?

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

Nó lấy Fragmentnhư một đối số, tạo ViewModelProviderđối tượng và chuyển trực tiếp đoạn tớiViewModelProvider tạo.

Chúng ta có thể sử dụng cùng một cách quá.

Ví dụ: Trước:

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

Sau:

OurViewModel mOurViewModel = new ViewModelProvider(this).get(OurViewModel.class);

Nếu bạn triển khai một Nhà máy, bạn có một cách khác: ViewModelProvidercó một nhà xây dựng mong đợi cả a ViewModelStoreOwnervà a Factory.
russellhoff


3

Tôi không phải là chuyên gia nhưng tôi có một dòng mã giải quyết vấn đề của tôi trong Java. Hy vọng điều này sẽ giúp được ai đó.

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

Như tôi đã nói tôi rất muốn cung cấp thêm chi tiết, nhưng điều này đã khắc phục vấn đề này cho tôi.


Mã này sai, onCleared()sẽ không được gọi theo cách này và ViewModel của bạn sẽ được tạo lại mỗi lần (không được giữ lại để thay đổi cấu hình).
EpicPandaForce

Bạn có thể giải thích thêm một chút với một ví dụ nhất định, điều gì sẽ sửa chữa lỗi lầm của tôi? Xin vui lòng, dán một tham chiếu đến lời giải thích hoặc bất cứ điều gì sẽ làm cho mọi thứ rõ ràng hơn
ZeePee

viewModel = new ViewModelProvider(this).get(MyViewModel.class). Nếu bạn AndroidViewModelkhông nhận được Application, thì bạn có một phiên bản không khớp giữa Vòng đời và Hoạt động / Mảnh vỡ.
EpicPandaForce

Ok, vậy gọi getApplicationContext là sai? Nó có nên là getContext không?
ZeePee

1
Vấn đề là tạo ra một new ViewModelProvider.AndroidViewModelFactory(thay vì a new ViewModelProvider(.
EpicPandaForce

3

Dùng cái này:

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

2

Bạn có thể sử dụng điều này thay thế:

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

"này" trong ngoặc đơn là chủ sở hữu của cá thể YourViewModel.


1

Câu trả lời này là dành cho Java nhưng bạn có thể hiểu ý chính. Giải pháp là bạn cần sử dụng ViewModelProviderViewModelProviders không dùng nữa :

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

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

Ví dụ sử dụng là:

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

Ngoài ra, đừng quên cập nhật Phụ thuộc cấp độ : Kiểm tra các phiên bản cuối cùng của chúng

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

!!! Tuy nhiên, hãy cẩn thận vì một số câu trả lời đề xuất giải pháp này nhưng nó không hiệu quả với tôi:

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

Bởi vì khi tôi sử dụng cách này, tôi đã nhận được bên dưới Thông báo lỗi:

Nguyên nhân do: java.lang.R.78Exception: Không thể tạo một thể hiện của lớp com.canerkaseler.mvvmexample.ViewModel

@canerkaseler


Câu trả lời này là sai. Bạn cần chuyển nhà máy đến ViewModelProvider. Nếu bạn trực tiếp gọi create, thì onCleared()sẽ không hoạt động chính xác.
EpicPandaForce

Trong thực tế, bạn thực sự chỉ nói không sử dụng câu trả lời chính xác. Âm thanh như bạn có một sự không phù hợp giữa bạn androidx.coreandroidx.lifecyclephụ thuộc của bạn .
EpicPandaForce

Thông thường tôi đã viết nhà máy cho ViewModelProvider. Tuy nhiên, bạn đã xóa nó. ContactViewModel contactViewModel = new ViewModelProvider.AndroidViewModelFactory (getApplication ()). Tạo (ContactViewModel. Class); Tại sao bạn xóa nó trên câu trả lời của tôi? Bạn đã thông qua mã sai.
canerkaseler

0

Khi bạn sử dụng dao găm thì bạn sẽ vượt qua nhà máy trong constructor

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

-2

Nếu bạn có triển khai này

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

Thử sử dụng viewModel = MainViewModel()


Đây không phải là một cách để khởi tạo một mô hình xem. Bạn phải sử dụng lớp ViewModelProvider cho điều đó
Emmanuel Mtali

-2

Thử cái này...

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

-5

nó nên hoạt động theo cách này

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

1
Mặc dù mã của bạn sẽ thể hiện lớp sẽ không tạo kết nối đến trạng thái xem được yêu cầu để có lớp Mô hình xem để đáp ứng chính xác các sự kiện trong vòng đời. Bạn cần thể hiện Mô hình Xem theo cách chính xác để họ phản hồi và tôn trọng vòng đời của cha mẹ họ, họ được tái tạo mới và trống mỗi lần.
Kenneth Argo

Như đã lưu ý ở trên bởi OP và những người khác; lớp ViewModelProviders không được dùng nữa. Xem: developer.android.com/reference/androidx/lifecycle/
trộm
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.