我应该在 ViewModel 中包含 LifecycleOwner 吗?
Should I include LifecycleOwner in ViewModel?
我目前需要 LifecycleOwner 才能创建观察者。
我有在 ViewModel 中创建 Observer 的代码,因此在我的 Fragment 中检索 ViewModel 时我附加了 LifecycleOwner。
根据 Google 的文档。
警告:ViewModel 绝不能引用视图、生命周期或任何可能包含对 activity 上下文的引用的 class。
我是否违反了该警告?如果违反了,您建议我如何移动我创建的数据观察器 return?
我只做了一个观察者,所以我想知道它是否仍然有效。因为在 Google 的文档中它也说了。
ViewModel 对象可以包含 LifecycleObservers,例如 LiveData 对象。
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:改进了 ViewModel,感谢 @pskink 关于使用转换的建议。
private lateinit var ipAddress:LiveData<String>
/**
* Improved ViewModel since January 23, 2018 credits to <a href="https://whosebug.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
}
假设:
Fuel
指的是你的ViewModel
Fuel.request(IpAddressApi.MyIp())
是您 ViewModel
中的一个方法
IpAddressApi.MyIp()
没有引用您的 LifecycleOwner
、
如果都是真的,那么你就没有违反它。只要您不传递 LifecycleOwner
对 ViewModel
的引用,您就是安全的!
LifecycleOwner - 与 Activity 或 Fragment 相关,因为它拥有各种 Android 生命周期,例如 onCreate、onPause、onDestroy 等
没有。如果您想观察 ViewModel
中某些 LiveData
的变化,您可以使用不需要 LifecycleOwner
.
的 observeForever()
记得在 ViewModel
的 onCleared()
事件中删除此观察者:
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。
在 Kotlin 中可以是这样的:
val mObserver = Observer<List<QueueTabData>> { myString->
// do something with myString
}
我目前需要 LifecycleOwner 才能创建观察者。
我有在 ViewModel 中创建 Observer 的代码,因此在我的 Fragment 中检索 ViewModel 时我附加了 LifecycleOwner。
根据 Google 的文档。
警告:ViewModel 绝不能引用视图、生命周期或任何可能包含对 activity 上下文的引用的 class。
我是否违反了该警告?如果违反了,您建议我如何移动我创建的数据观察器 return?
我只做了一个观察者,所以我想知道它是否仍然有效。因为在 Google 的文档中它也说了。
ViewModel 对象可以包含 LifecycleObservers,例如 LiveData 对象。
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:改进了 ViewModel,感谢 @pskink 关于使用转换的建议。
private lateinit var ipAddress:LiveData<String>
/**
* Improved ViewModel since January 23, 2018 credits to <a href="https://whosebug.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
}
假设:
Fuel
指的是你的ViewModel
Fuel.request(IpAddressApi.MyIp())
是您ViewModel
中的一个方法
IpAddressApi.MyIp()
没有引用您的LifecycleOwner
、
如果都是真的,那么你就没有违反它。只要您不传递 LifecycleOwner
对 ViewModel
的引用,您就是安全的!
LifecycleOwner - 与 Activity 或 Fragment 相关,因为它拥有各种 Android 生命周期,例如 onCreate、onPause、onDestroy 等
没有。如果您想观察 ViewModel
中某些 LiveData
的变化,您可以使用不需要 LifecycleOwner
.
observeForever()
记得在 ViewModel
的 onCleared()
事件中删除此观察者:
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。
在 Kotlin 中可以是这样的:
val mObserver = Observer<List<QueueTabData>> { myString->
// do something with myString
}