web-dev-qa-db-fra.com

Dois-je inclure LifecycleOwner dans ViewModel?

LifecycleOwner est actuellement nécessaire pour que je puisse créer un observateur.

J'ai du code qui crée un observateur dans le ViewModel, donc j'attache le LifecycleOwner lors de la récupération du ViewModel dans mon fragment.

Selon la documentation de Google.

Attention: un ViewModel ne doit jamais référencer une vue, un cycle de vie ou toute classe pouvant contenir une référence au contexte d'activité.

Ai-je rompu cet avertissement et si je l'ai fait, de quelle manière me recommandez-vous de déplacer ma création d'un observateur pour le retour des données?

Je n'ai fait qu'un observateur donc je me demande si c'est toujours valable. Depuis également dans la documentation de Google, il a également dit.

Les objets ViewModel peuvent contenir des LifecycleObservers, tels que des objets 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
}

Mise à jour 1: ViewModel amélioré grâce à la suggestion @pskink pour l'utilisation des 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
}
15
Hiroga Katageri

Non. Si vous souhaitez observer les changements de certaines LiveData dans votre ViewModel, vous pouvez utiliser observeForever () qui ne nécessite pas LifecicleOwner. N'oubliez pas de supprimer cet observateur lors de l'événement ViewModels 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()
}

Très bonne référence avec des exemples de observez LiveData .

11
Vitaliy A

Hypothèses:

  1. Fuel fait référence à votre ViewModel
  2. Fuel.request(IpAddressApi.MyIp()) est une méthode dans votre ViewModel
  3. IpAddressApi.MyIp() n'a pas de référence à votre LifecycleOwner,

Si tout est vrai, vous ne le violez pas. Tant que vous ne passez pas une référence LifecycleOwner au ViewModel, vous êtes en sécurité!

LifecycleOwner - se rapporte à une activité ou à un fragment car il possède les différents cycles de vie Android par exemple onCreate, onPause, onDestroy, etc.

1
martinomburajr