【问题标题】:LiveData. Cannot assign to ‘value’: the setter is protected/*protected and package*/ for synthetic extension实时数据。无法分配给“值”:setter 受保护/*受保护并打包*/ 用于合成扩展
【发布时间】:2018-06-19 07:54:14
【问题描述】:

我正在尝试使用 android documentation 中描述的 LiveData 实现 DB Observer。

只要我在 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>’

有人遇到过这个问题吗?

这是我的代码:

视图模型:

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

【问题讨论】:

  • fun getCurrentName(): MutableLiveData&lt;String&gt;替换fun getCurrentName(): LiveData&lt;String&gt;
  • 是的,这就是问题所在。您能否详细说明一下答案,以便我们为社区保留它?
  • 查看LiveData#setValue()MutableLiveData#setValue() 方法的区别

标签: android kotlin android-architecture-components android-livedata


【解决方案1】:

正如@spkink 建议的那样:

替换

fun getCurrentName(): LiveData<String>

fun getCurrentName(): MutableLiveData<String>

这个错误是因为setValue(T value)在LiveData中是protected(所以你不能调用它)而在MutableLiveData中是public

【讨论】:

    【解决方案2】:
    model.getCurrentName().value = firstName
    

    请考虑在 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
    }
    

    片段

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

    【讨论】:

      猜你喜欢
      • 2012-09-05
      • 1970-01-01
      • 2014-10-11
      • 2014-03-05
      • 2016-02-19
      • 1970-01-01
      • 2020-03-31
      • 2011-09-04
      • 1970-01-01
      相关资源
      最近更新 更多