【问题标题】:Should I include LifecycleOwner in ViewModel?我应该在 ViewModel 中包含 LifecycleOwner 吗?
【发布时间】:2018-07-01 22:34:37
【问题描述】:

目前需要 LifecycleOwner 才能创建观察者。

我有在 ViewModel 中创建 Observer 的代码,因此我在 Fragment 中检索 ViewModel 时附加了 LifecycleOwner。

根据 Google 的文档。

注意:ViewModel 绝不能引用视图、生命周期或任何可能持有对活动上下文的引用的类。

我是否打破了该警告?如果我打破了,您建议我以什么方式移动我创建的观察者以进行数据返回?

我只做了一个观察者,所以我想知道它是否仍然有效。因为也在谷歌的文档中也说过。

ViewModel 对象可以包含 LifecycleObservers,例如 LiveData 对象。

主片段

private lateinit var model: MainViewModel

/**
 * Observer for our ViewModel IpAddress LiveData value.
 * @see Observer.onChanged
 * */
private val ipObserver = Observer<String> {
    textIp.text = it
    hideProgressBar()
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    model = ViewModelProviders.of(this).get(MainViewModel::class.java)
    model.attach(this)
}

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? =
        inflater?.inflate(R.layout.fragment_main, container, false)

override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    buttonRetrieveIp.setOnClickListener {
        showProgressBar()
        model.fetchMyIp().observe(this, ipObserver) //Here we attach our ipObserver
    }
}

override fun showProgressBar() {

    textIp.visibility = View.GONE
    progressBar.visibility = View.VISIBLE
}

override fun hideProgressBar() {

    progressBar.visibility = View.GONE
    textIp.visibility = View.VISIBLE
}

MainViewModel

private var ipAddress = MutableLiveData<String>()
private lateinit var owner: LifecycleOwner

fun attach(fragment: MainFragment) {
    owner = fragment
}

/**
 * For more information regarding Fuel Request using Fuel Routing and Live Data Response.
 * @see <a href="https://github.com/kittinunf/Fuel#routing-support">Fuel Routing Support</a>
 * @see <a href="https://github.com/kittinunf/Fuel#livedata-support">Fuel LiveData Support</a>
 * */
fun fetchMyIp(): LiveData<String> {

    Fuel.request(IpAddressApi.MyIp())
            .liveDataResponse()
            .observe(owner, Observer {

                if (it?.first?.statusCode == 200) {//If you want you can add a status code checker here.

                    it.second.success {

                        ipAddress.value = Ip.toIp(String(it))?.ip
                    }
                }
            })
    return ipAddress
}

更新 1:改进了 ViewModel,感谢 @pskink 建议使用转换。

private lateinit var ipAddress:LiveData<String>

/**
 * Improved ViewModel since January 23, 2018 credits to <a href="https://stackoverflow.com/users/2252830/pskink">pskink</a> <a href="
 *
 * For more information regarding Fuel Request using Fuel Routing and Live Data Response.
 * @see <a href="https://github.com/kittinunf/Fuel#routing-support">Fuel Routing Support</a>
 * @see <a href="https://github.com/kittinunf/Fuel#livedata-support">Fuel LiveData Support</a>
 * */
fun fetchMyIp(): LiveData<String> {

    ipAddress = Transformations.map(Fuel.request(IpAddressApi.MyIp()).liveDataResponse(), {

        var ip:String? = ""

            it.second.success {

                ip = Ip.toIp(String(it))?.ip
            }
        ip
    })

    return ipAddress
}

【问题讨论】:

  • 试过MediatorLiveDataTransformations#map / Transformations#switchMap?
  • 实际上我还没有,所以我将返回一个 MediatorLiveData 并添加两个源并在我的片段中添加一个观察者,而不是返回一个 LiveData 字符串,对吧?
  • 首先尝试Transformations 类- 似乎这是最简单的方法- 如果不是,当谈到MediatorLiveData 时,您所说的“两个来源”是什么意思?有一个来源会发生变化,不是吗?
  • 我现在明白了,我能够使用转换使其工作。

标签: android mvvm android-viewmodel


【解决方案1】:

没有。如果你想观察你的ViewModel 中的一些LiveData 的变化,你可以使用observeForever(),它不需要LifecycleOwner

记得在ViewModelonCleared() 事件中删除这个观察者:

val observer = new Observer() {
  override public void onChanged(Integer integer) {
    //Do something with "integer"
  }
}

...

liveData.observeForever(observer);

...

override fun onCleared() {
    liveData.removeObserver(observer) 
    super.onCleared()
}

很好的参考,有observe LiveData的例子。

【讨论】:

    【解决方案2】:

    假设:

    1. Fuel 指您的ViewModel
    2. Fuel.request(IpAddressApi.MyIp()) 是您的 ViewModel 中的一个方法
    3. IpAddressApi.MyIp() 没有引用您的 LifecycleOwner

    如果一切都是真的,那么你就没有违反它。只要您没有将LifecycleOwner 引用传递给ViewModel,您就是安全的!

    LifecycleOwner - 与 Activity 或 Fragment 相关,因为它拥有各种 Android 生命周期,例如 onCreate、onPause、onDestroy 等

    【讨论】:

    • 我已经用其他信息更新了我的问题。 Fuel 是我的 HttpClient,Fuel.request 是 Fuel 中的一个方法,它将 FuelRouting 接口转换为请求,我在这里为我的 GET 方法的返回创建了一个观察者。
    【解决方案3】:

    Kotlin 中可以是这样的:

    val mObserver = Observer<List<QueueTabData>> { myString->
    // do something with myString
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-20
      • 2011-01-31
      • 2015-10-08
      • 1970-01-01
      • 1970-01-01
      • 2013-02-23
      • 2011-12-19
      • 1970-01-01
      相关资源
      最近更新 更多