我应该在ViewModel中包括LifecycleOwner吗? [英] Should I include LifecycleOwner in ViewModel?

查看:92
本文介绍了我应该在ViewModel中包括LifecycleOwner吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前需要LifecycleOwner才能创建观察者.

LifecycleOwner is currently needed in order for me to create an observer.

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

I have code which creates an Observer in the ViewModel so I attach the LifecycleOwner when retrieving the ViewModel in my Fragment.

根据Google的文档.

According to Google's documentation.

警告:ViewModel绝不能引用视图,生命周期或任何可能包含对活动上下文的引用的类.

Caution: A ViewModel must never reference a view, Lifecycle, or any class that may hold a reference to the activity context.

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

Did I break that warning and If I did, what way do you recommend me to move my creation of an observer for data return?

我只是做一个观察者,所以我想知道它是否仍然有效.由于在Google的文档中也有提及.

I only made an observer so I'm wondering if it's still valid. Since also in Google's documentation it also said.

ViewModel对象可以包含LifecycleObserver,例如LiveData对象.

ViewModel objects can contain LifecycleObservers, such as LiveData objects.

MainFragment

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:由于@pskink建议使用Transformations,因此改进了ViewModel.

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
}

推荐答案

否.如果您希望观察ViewModel内部某些LiveData的变化,则可以使用无需LifecicleOwner的observeForever(). 记住要在ViewModels onCleared()事件上删除此观察器:

No. If you wish to observe changes of some LiveData inside your ViewModel you can use observeForever() which doesn't require LifecicleOwner. Remember to remove this observer on ViewModels onCleared() event:

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

很好地参考了观察LiveData 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆