LiveData.无法赋值给'value':setter对于合成扩展是受保护的/*受保护和包*/。

47

我正在尝试按照安卓文档中描述的使用LiveData实现数据库观察者模式。

由于我用的是Kotlin编程语言,所以我正在将函数(原本是用Java编写的)适应到它上面。

在尝试保存数据时,我遇到了这个问题。

Cannot assign to ‘value’: the setter is protected/*protected and package*/ for synthetic extension in ‘<library Grade: android.arch.livecycle:livedata-core-1.1.1>’

有人遇到过这个问题吗?

这是我的代码:

ViewModel:

class ProfileViewModel: ViewModel() {

    object FirstName: MutableLiveData<String>()

    fun getCurrentName(): LiveData<String> {
        return FirstName
    }
}

片段

class ProfileFragment{

    private lateinit var model: ProfileViewModel

    // this is called onViewCreated. inputFirstName is an Edittext.
    override fun setUp() {
        model = ViewModelProviders.of(this).get(ProfileViewModel::class.java)

        val nameObserver = Observer<String> { firstName ->
            inputFirstName.text = SpannableStringBuilder(firstName)
        }

        model.getCurrentName().observe(this, nameObserver)
    }

    fun saveProfileData() {
        val firstName = inputFirstName.text.toString()
        model.getCurrentName().value = firstName
    }
}

6
fun getCurrentName(): LiveData<String> 替换为 fun getCurrentName(): MutableLiveData<String> - pskink
是的,那就是问题所在。您能否详细说明一下答案,以便我们可以为社区保留它? - kike
2
查看LiveData#setValue()MutableLiveData#setValue()方法之间的区别。 - pskink
2个回答

67
作为 @spkink 建议的一部分,替换:
fun getCurrentName(): LiveData<String>

使用

fun getCurrentName(): MutableLiveData<String>

错误是由于LiveData中的setValue(T value)受到保护而无法调用,而在MutableLiveData中它是公共的,因此导致的。

1
model.getCurrentName().value = firstName

请注意,在ViewModel内处理名称值更新可能是一种更清晰的解决方案,因为您避免了具有可变公共属性的情况。此外,这里可能会导致更糟糕的影响,因为您有两个可变的公共LiveData属性。例如:

ViewModel

// keep your MutableLiveData private, so it's easier to find where mutations might happen in your code
// I changed a little how the variable is declared, as the way below seems to more common nowadays
private var _firstName = MutableLiveData<String>()

// LiveData should remain public, being a read-only interface with other classes like your fragment
fun getCurrentName(): LiveData<String> {
    return _firstName
}

/*
An alternative 
val firstName = LiveData<String>
    get() = _firstName
*/

fun setFirstName(firstName: String){
    _firstName.value = firstName
}

Fragment

fun saveProfileData() {
    val firstName = inputFirstName.text.toString()
    // the value update will be handled inside the ViewModel, where the private mutable live data property is located
    model.setFirstName(firstName)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接