【问题标题】:LiveData is abstract androidLiveData 是抽象的 android
【发布时间】:2017-08-10 22:17:22
【问题描述】:

我尝试初始化我的 LiveData 对象,但它给出了错误:“LiveData 是抽象的,它不能被实例化”

LiveData 列表LiveData = new LiveData();

【问题讨论】:

  • 你是如何初始化你的对象的?请包含您的代码,以便我们了解发生了什么。
  • 嗯,那是因为LiveData 是abstract。您到底想在这里用LiveData 做什么?您要么需要创建LiveData 的子类,要么使用MutableLiveData。

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


【解决方案1】:

在 ViewModel 中,您可能希望改用 MutableLiveData。

例如:

class MyViewModel extends ViewModel {
  private MutableLiveData<String> data = new MutableLiveData<>();

  public LiveData<String> getData() {
    return data;
  }

  public void loadData() {
    // Do some stuff to load the data... then
    data.setValue("new data"); // Or use data.postValue()
  }
}

或者,在 Kotlin 中:

class MyViewModel : ViewModel() {
  private val _data = MutableLiveData<String>()
  val data: LiveData<String> = _data

  fun loadData() {
    viewModelScope.launch {
      val result = // ... execute some background tasks
      _data.value = result
    }
  }
}

【讨论】:

  • 你不需要在 getData(){} 中调用 loadData(),就在“返回数据”的上方吗?
  • 取决于您的应用。可能您想调用一次loadData(),但从几个不同的地方调用getData()。 ViewModel 可以尝试在何时调用 loadData() 时变得聪明,或者让调用者选择何时最好这样做(例如,用户滑动刷新)。
【解决方案2】:

由于它是抽象的(正如@CommonsWare 所说),您需要将其扩展为子类,然后按照表单中的要求覆盖方法:

public class LiveDataSubClass extends LiveData<Location> {

}

见docs for more details

【讨论】:

    【解决方案3】:

    是的,你不能实例化它,因为它是一个抽象类。如果要在实时数据对象中设置值,可以尝试使用 MutableLiveData。如果您想观察其他 livedata 对象,也可以使用Mediator live data。

    【讨论】:

      【解决方案4】:

      您需要使用 MutableLiveData,然后将其转换为其父类 LiveData。

      公共类 MutableLiveData 扩展 LiveData

      [MutableLiveData is] LiveData 公开了 setValue(T) 和 postValue(T) 方法。

      你可以这样做:

      fun initializeLiveData(foo: String): LiveData<String> {
          return MutableLiveData<String>(foo)
      }
      

      那么你得到:

      Log.d("now it is LiveData", initializeLiveData("bar").value.toString())
      // prints "D/now it is LiveData: bar"
      

      【讨论】:

        【解决方案5】:

        我认为实现这一点的更好方法是使用我们所说的 Backing Property 来实现更好的 Encapsulation 属性。

        使用示例:

        private val _userPoints = MutableLiveData<Int>()// used as a private member
        
        val userPoints: LiveData<Int>
            get() {
                return _userPoints 
            } //used to access the value inside the UI controller (Fragment/Activity). 
        

        这样做会维护一个可编辑的MutableLiveData 私有到ViewModel 类,而它的read-only 版本被维护为LiveData,getter 返回原始值。

        附: - 注意两个字段的命名约定,使用 (_) 下划线。这不是强制性的,但建议这样做。

        【讨论】:

        • 每次看到_作为backing field的前缀,我都在想private val blah + fun blah()最终会不会更受欢迎。
        • @EpicPandaForce 哈哈哈!是的,你在那里提出了一个坚实的观点。这些天有很多符号。有时阅读博客可能会掩盖您对正在学习或已经成为专家的语言的理解。只能依赖Android官方的代码示例和实践。
        • 哦,伙计,我已经在足够多的 Android 官方代码示例中看到了足够多的错误,我不确定我是否会如此确定地大声说出来 - 我最喜欢的奇怪之处是架构示例 Todo-MVVM他们使字段/类可变以使双向绑定起作用,但没有更新文档并说“这是一个不可变的类……”而且他们不使用自己的工具,例如 SavedStateHandle。 Iosched 比它要解决的问题复杂得多。也许这只是我的看法,但我编写的应用程序更复杂,管道更少。
        猜你喜欢
        • 2020-05-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多