LifecycleOwner is currently needed in order for me to create an observer.
I have code which creates an Observer in the ViewModel so I attach the LifecycleOwner when retrieving the ViewModel in my Fragment.
According to Google's documentation.
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?
I only made an observer so I'm wondering if it's still valid. Since also in Google's documentation it also said.
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
}
Update 1: Improved ViewModel thanks to @pskink suggestion for using Transformations.
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
}
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…