web-dev-qa-db-fra.com

Réagir au cycle de vie d'une activité dans ViewModel

J'essaie de créer une application qui utilisera l'architecture MVVM et il y a une chose que je ne comprends pas du tout.

Officiel Android disent que ce n'est pas une bonne idée de référencer le contexte d'activité dans ViewModel (car ViewModel peut survivre à l'activité), j'ai donc commencé à me demander à propos de l'utilisation lorsque je veux exécuter une action lorsque mon activité reprend.

Je sais que ViewModel ne devrait pas faire lui-même la logique métier, mais même si j'utilise une classe de service (disons que GPSService qui doit démarrer et suspendre chaque activité est reprise en pause), et à l'intérieur de ce service, je réagis à l'activité onResume (en utilisant l'observateur du cycle de vie) Je vais toujours référencer cette activité à partir de ViewModel car je fais référence à un service qui contient une référence à l'activité observée, cela peut provoquer une fuite d'activité (corrigez-moi si je me trompe).

Ma question est donc la suivante: comment réagir à l'activité ou au cycle de vie des fragments dans l'architecture MVVM?

13
Androider

Je sais que ViewModel ne devrait pas faire lui-même la logique métier

Oui tu as raison. ViewModel ne doit pas contenir de logique métier mais doit contenir une logique liée à l'interface utilisateur. Donc, fondamentalement, les appels API ou certains éléments liés à l'emplacement doivent être évités dans la logique ViewModel.

Et si vous voulez créer un scénario qui peut réagir à n'importe quel cycle de vie d'une activité? Je vous suggère d'utiliser LifecycleObserver .

Pourquoi?, Parce que LifecycleObserver vous fournira des rappels une fois que c'est LifecycleOwner will changer son état.

Qu'est-ce que LifecycleOwner ici? Dans notre cas, cela peut être Activité/Fragment .


Alors, comment pouvez-vous y parvenir?

Supposons que vous souhaitiez effectuer des demandes de localisation pendant reprise et pause période de toute activité.

Donc, pour cela, vous pouvez créer une classe appelée LocationUpdates comme LifecycleObserver comme ci-dessous:

class LocationUpdates : LifecycleObserver {

constructor(){
    // some basic location related initialization here
}

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun connectListener() {
    // this method will respond to resume event of our Lifecycle owner (activity/fragment in our case)
   // So let's get location here and provide callback
}

@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun disconnectListener() {
    // this method will respond to pause event of our Lifecycle owner (activity/fragment in our case)
   // So let's stop receiveing location updates here and remove callback
}

@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) // Optional if you want to cleanup references
fun cleanUp() {
    // this method will respond to destroy event of our Lifecycle owner (activity/fragment in our case)
   // Clean up code here
}
}

Maintenant, à partir de votre activité, vous pouvez directement créer votre LocationUpdates et recevoir un rappel.

class MyActivity : AppCompatActivity() {

private lateinit var mLocationUpdates: LocationUpdates

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    //Initialize your LifecycleObserver here & assign it to this activity's lifecycle
    lifecycle.addObserver(mLocationUpdates)
}
}

Vous pouvez vous référer à comment gérer le cycle de vie & exemple Codelabs.


Éditer:

Si vous voulez avoir ViewModel pour ce travail, considérez ceci:

class MyViewModel : ViewModel {
private lateinit var mLocationUpdates: LocationUpdates

constructor() : super() {
    // initialize LocationUpdates here
}

// Assign our LifecyclerObserver to LifecycleOwner
fun addLocationUpdates(lifecycle: Lifecycle){
    lifecycle.addObserver(mLocationUpdates)
}

//Optional, we really don't need this.
fun removeLocationUpdates(lifecycle: Lifecycle){
    lifecycle.removeObserver(mLocationUpdates)
}
}

Si votre LocationUpdates dépend de Context, pensez à utiliser AndroidViewModel.

Nous pouvons maintenant observer nos mises à jour de localisation @ toute activité/fragment en utilisant LiveData, et affecter notre LifecycleObserver comme ci-dessous:

class MyActivity : AppCompatActivity() {

private val viewModel: MyViewModel by lazy {
    return@lazy ViewModelProviders.of(this@MyActivity).get(MyViewModel::class.Java)
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    viewModel.addLocationUpdates(lifecycle)
}
}

Veuillez noter: il y a encore beaucoup à couvrir mais rendre cette réponse aussi courte que possible. Donc, si vous êtes toujours confus à propos de quelque chose de similaire, n'hésitez pas à me le demander en commentaire. Je vais modifier ma réponse.

7
Jeel Vankhede

Si vous avez besoin qu'un ViewModel soit sensible au cycle de vie, vous pouvez le faire implémenter LifeCycleObserver et remplacer les événements du cycle de vie si nécessaire. Exemple,

public class MyModel extends ViewModel implements
    LifecycleObserver {

  @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
  protected void onLifeCycleStop() {
      // do something
  }
}

Dans l'activité ou le fragment, vous pouvez ensuite ajouter le modèle de vue au propriétaire du cycle de vie de l'activité.

public class MyActivity extends AppCompatActivity {

  protected MyModel mMyModel;

  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      mMyModel = ViewModelProviders
          .of(this)
          .get(MyModel.class);

      getLifecycle().addObserver(mMyModel);
  }
}
0
farid_z