首页 > 解决方案 > Kotlin 中的接收器类型与 Android 的 `activityViewModels` 不匹配

问题描述

很多年没有接触过 Android,也根本没有真正接触过 Kotlin。我的Fragment有以下之一:

package com.example.my_frag

import androidx.lifecycle.ViewModel
import androidx.fragment.app.activityViewModels
import com.example.MainViewModel


class MyFragViewModel : ViewModel() {
    private val viewModel: MainViewModel by activityViewModels<MainViewModel>()
}

为了完成,这里是Fragment

package com.example.my_frag

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.ListView
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.example.R


class MyFragment : Fragment() {
    private lateinit var myFragViewModel: MyFragViewModel

    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        myFragViewModel =
                ViewModelProvider(this).get(MyFragViewModel::class.java)
        val root = inflater.inflate(R.layout.fragment_my, container, false)
        return root
    }
}

……我的Activity样子:

package com.example

import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer


class MainActivity : AppCompatActivity() {
    private val viewModel: MainViewModel by viewModels<MainViewModel>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewModel.selectedItem.observe(this, Observer { item ->
            println("$item observed")
        })
    }
}

随着ViewModel存在:

package com.example

import android.view.MenuItem
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel


class MainViewModel : ViewModel() {
    private val mutableSelectedItem = MutableLiveData<MenuItem>()
    val selectedItem: LiveData<MenuItem> get() = mutableSelectedItem

    fun selectItem(item: MenuItem) {
        mutableSelectedItem.value = item
    }
}

我小心地添加到我的build.gradle这些dependencies

dependencies {
    implementation "android.arch.lifecycle:extensions:1.1.1"
    implementation "androidx.fragment:fragment-ktx:1.2.5"
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'androidx.core:core-ktx:1.3.2'
    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
    implementation 'androidx.navigation:navigation-fragment-ktx:2.3.2'
    implementation 'androidx.navigation:navigation-ui-ktx:2.3.2'
    implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'com.google.android.material:material:1.2.1'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

但是它不起作用,activityViewModels以红色突出显示,错误是:

未解决的参考。由于接收器类型不匹配,以下候选均不适用: public inline fun <reified VM : ViewModel> Fragment.activityViewModels(noinline factoryProducer: (() -> ViewModelProvider.Factory)? = ...): Lazy<TypeVariable(VM)>定义于androidx.fragment.app

我如何使用这种模式?

标签: androidkotlinandroid-fragmentsandroid-activityandroid-viewmodel

解决方案


这条线

private val viewModel: MainViewModel by activityViewModels<MainViewModel>()

应该进入您的 Fragment 类,而不是您的其他 ViewModel 类。activityViewModels()是 Fragment 的函数,而不是 ViewModel。ViewModel 不应相互引用。它们的范围仅限于 Activity 或 Fragment 的生命周期,并且没有其他 ViewModel 可以附加到的自己的大写 L 生命周期。


推荐阅读