Composants d'architecture Android Lifecycle et LiveModel

Dans la dernière partie de cette série, Introduction aux composants de l'architecture Android, nous avons parlé de la nouvelle architecture Android et de la raison pour laquelle elle a été développée. Fondamentalement, la nouvelle architecture résout certains problèmes connus d'Android en proposant un ensemble de composants conçus sur mesure pour le système. Ce sont les blocs de construction de l'architecture. Nous avons déjà examiné ces composants, il est donc temps de commencer à les explorer. 

Dans ce tutoriel, nous examinerons de près le Cycle de la vie et le LiveModel Composants. Pendant notre exploration, nous allons également extraire des extraits de code d’un exemple d’application. Puisque nous parlons des nouveaux paradigmes d’Android, les extraits sont tous fabriqués avec l’impressionnant Kotlin.

Si vous ne connaissez pas encore Kotlin, n’ayez pas peur de vous suivre; l'implémentation est extrêmement proche de Java et je suis convaincu que vous pourrez le comprendre. Si vous souhaitez en savoir plus sur Kotlin, Jessica Thornsby a écrit une excellente série ici sur Tuts + à propos du codage d’applications Android à Kotlin. Vous devriez jeter un oeil!

  • Codage d'applications Android fonctionnelles dans Kotlin: Mise en route

    Entendu des choses positives sur la langue Kotlin pour les applications Android et que vous voulez l'essayer vous-même? Découvrez comment configurer et commencer à coder dans cette nouvelle…
    Jessica Thornsby
    Studio Android
  • Codage d'applications Android fonctionnelles dans Kotlin: Lambdas, Null Safety & More

    Le langage Kotlin pour les applications Android vous permet de coder de manière beaucoup plus détaillée en Java, ou impossible avec Java seul. Apprendre…
    Jessica Thornsby
    SDK Android

1. Le projet exemple

Nous avons fourni une petite application illustrant les concepts évoqués dans ce didacticiel. L'application s'appelle MyWeatherApp et permet à l'utilisateur de consulter la météo du jour à l'aide du nom d'une ville ou de sa position actuelle. La logique de l'application est assez simple, mais vous pouvez l'améliorer pour créer votre propre application..

Comme vous pouvez le voir sur le schéma ci-dessous, l'architecture est conforme à celle proposée par Android et nous avons utilisé le plus possible le nouveau package Architecture Components, en maintenant les choses suffisamment simples pour une analyse de base. En prime, nous utilisons Dagger 2 en tant que bibliothèque d'injection de dépendance. Cependant, nous n'entrerons pas dans les détails de son implémentation, car cela échapperait à la portée du tutoriel..

Comment fonctionne l'application?

L'application est aussi simple que possible. Il a une seule activité, où l'utilisateur peut obtenir la météo en recherchant le nom d'une ville ou en utilisant l'emplacement actuel de l'appareil. le Activité principale appelle le MainModel obtenir un observable Données en direct et y réagit. le MainModel récupère les données météorologiques du MainRepository, et consolide toutes les données en tant que Données en direct. le MainRepository obtient ses données de plusieurs sources.

Exécution de l'exemple d'application

Téléchargez ou clonez le référentiel à partir de notre référentiel GitHub et construisez-le avec Gradle ou ouvrez-le dans votre IDE. Vous devez également créer un compte OpenWeatherMap et obtenir un nouvel ID d'application. Ajoutez l'ID d'application sur une ressource de chaîne appelée temps ouvert.

XXXXXXXXXXXXXXX

2. Mise en place d'un projet

Les composants d’architecture étant toujours en alpha, vous devez inclure le référentiel Google, qui contient des bibliothèques expérimentales, dans le projet. build.gradle.

allprojects repositories // ajouter ce maven de référentiel url 'https://maven.google.com'

Dans le module build.gradle, ajoutez ce qui suit au les dépendances section pour ajouter le support pour Les cycles de la vieDonnées en direct, et ViewModel:

  • compile "android.arch.lifecycle: runtime: 1.0.0-alpha5"
  • compile "android.arch.lifecycle: extensions: 1.0.0-alpha5"
  • annotationProcessor "android.arch.lifecycle: compiler: 1.0.0-alpha5"

Si vous utilisez Kotlin, vous devez également ajouter ou remplacer le annotationProcessor avec kapt, qui gère les annotations sur Kotlin.

kapt "android.arch.lifecycle: compiler: 1.0.0-alpha5"

Autoriser kapt, ajouter ce qui suit dans le module build.gradle racine.

kapt generateStubs = true

3. Le Cycle de la vie Composant

Tous les développeurs Android connaissent le concept de cycle de vie. Le système gère le cycle de vie des applications, activités, fragments, etc., sans le contrôle du développeur. Ce concept est l’un des paradigmes d’Android et, jusqu’à récemment, il n’était pas facile de travailler avec, car il n’était pas possible de vérifier directement l’état actuel du cycle de vie d’un composant. Ce que nous pouvions faire était de réagir à certaines méthodes, comme onCreate et onDestroy, déclenché par des événements de cycle de vie.

Tout a changé depuis l’annonce du paquet Architecture Components, qui a introduit un composant appelé Cycle de la vie. Maintenant, certains objets Android ont un Cycle de la vie attaché à eux, et cela change beaucoup de choses pour les développeurs. Il est possible de consulter un Cycle de la vie état à un moment donné, et il est également possible de réagir à Cycle de la vie événements utilisant des annotations. En fait, l’épine dorsale des nouveaux composants d’architecture Android est la Cycle de la vie composant.

Tous les éléments du package android.arch.lifecycle sont importants pour la cycle de la vie concept, mais deux d’entre eux méritent plus d’attention: Cycle de vie et LifecycleObserver. Ils créent la possibilité de travailler avec Cycle de la vie, observer et réagir aux événements qui se produisent sur les activités, fragments, services, etc..

le Cycle de vie

le Cycle de vie est une interface de méthode unique pour les classes contenant un Cycle de la vie. Il fait abstraction de la possession d'un Cycle de la vie, vous permettant d'écrire des composants qui peuvent fonctionner avec elle. Selon les nouvelles normes, les activités et les fragments sont Cycle de vies. Toutefois, jusqu'au lancement de la version finale des composants d'architecture, vous devez utiliser certaines classes spéciales: Cycle de vie d'activitéFragmentLifecycle, et LifecycleService.

class MainActivity: LifecycleActivity () substitue l'amusement onCreate (savedInstanceState: Bundle?) super.onCreate (savedInstanceState)

Il n'y a pas de changement significatif dans la mise en œuvre de ces classes par rapport aux activités et fragments standard. Une fois qu'une classe se prolonge, elle aura un Cycle de la vie attaché, qui peut être récupéré à tout moment avec la méthode getLifecycle (). Une autre possibilité intéressante est que nous pouvons vérifier l'état actuel du cycle de vie avec getCurrentState, qui retourne un Cycle de vie.État

Il y a cinq différents Cycle de la vie États:

  • INITIALISE: pour un objet qui a été appelé, mais qui n'est pas encore "actif". C'est l'équivalent d'un état avant le Activité.Créer méthode.
  • CRÉÉ: pour les objets qui viennent d'être créés. Il s'appelle après le onCreate méthode et aussi appelée juste avant la onStop méthode.
  • COMMENCÉ: appelé après le onStart et juste avant le onPause méthode.
  • A REPRIS: L'état actif ou l'état repris pour un Cycle de vie. Appelé après le pour résumer méthode.
  • DÉTRUIT: pour un détruit Cycle de vie objet. Ce Cycle de la vie ne pas envoyer plus d'événements. Cet événement est atteint juste avant le onDestroy méthode.

le LifecycleObserver

Une des propriétés les plus intéressantes de la Cycle de la vie est-ce qu'il peut être facilement observé.  LifecycleObserver les classes peuvent observer Cycle de vie composants, comme les activités et les fragments. Il reçoit LifecycleOwner.Events, et peut y réagir grâce à l'annotation @OnLifeCycleEvent (Lifecycle.Event).

classe MainObserver: LifecycleObserver, AnkoLogger @OnLifecycleEvent (Lifecycle.Event.ON_RESUME) fun onResult () info ("onResult") @OnLifecycleEvent (Lifecycle.Event.ON_STOP) fun onStop ()

Les méthodes annotées avec @OnLifecycleEvent pas besoin d'arguments, mais s'il est utilisé, le premier argument doit être le Cycle de vie. Quand l'annotation utilise Lifecycle.Event.ON_ANY, la méthode devrait attendre deux arguments: Cycle de vie et Lifecycle.Event.

@OnLifecycleEvent (Lifecycle.Event.ON_ANY) fun onEvent (propriétaire: LifecycleOwner, événement: Lifecycle.Event) info ("onEvent: ownerState: $ propriétaire.lifecycle.currentState") info ("onEvent: event: $ event" )

Pour activer le @OnLifecycleEvent annotation, la LifecycleObserver doit observer un Cycle de la vie, sinon, il ne recevra pas l'événement. Pour que cela fonctionne, appelez Lifecycle.addObserver (LifecycleOwner) et le Cycle de vie sera ensuite en mesure de réagir à Lifecycle.Event. Il est également possible d'appeler Lifecycle.removeObsever (LifecycleObserver) enlever un observateur.

class MainActivity: LifecycleActivity (), AnkoLogger @Inject lateinit var mainObserver: MainObserver remplace Fun surCreate (savedInstanceState: Bundle?) //… // sur Kotlin, au lieu de getLifecycle, // nous pouvons appeler lifecycle directement lifecycle.addObserver ) écraser sur onDestroy () //… lifecycle.removeObserver (mainObserver)

Il existe divers cas d’utilisation intéressants pour LifecycleObserver. Par exemple, il pourrait être utilisé pour créer un Présentateur couche du modèle d’architecture de Model View Presenter. Il pourrait également être utilisé pour créer des auditeurs pouvant cesser d’écouter lorsque le Cycle de la vie est désactivé.

4. Le LiveModel Composant

Conçu pour fonctionner avec la couche d'interface utilisateur, le ViewModel Ce composant comble une lacune existant depuis le début dans Android: il permet de gérer et de stocker avec élégance des objets de données liés à la vue. Le composant maintient l'intégrité des données entre les modifications de configuration, peut être partagé entre Activity et Fragments et constitue un excellent outil pour éviter complètement les fuites de mémoire..

le ViewModel est toujours créé en relation étroite avec une portée spécifique, une activité ou un fragment. L'étendue est conservée tant que l'activité ou le fragment est en vie. Concrètement, le ViewModel se reconnecte avec la vue après les changements de configuration, en se maintenant jusqu'à la destruction de la vue principale. Selon la documentation officielle:

Le but de la ViewModel est d'acquérir et de conserver les informations nécessaires à une activité ou à un fragment.

En plus de tout ça, le ViewModel facilite la séparation des préoccupations dans le processus de développement Android. En déplaçant toutes les opérations liées aux données vers ce composant et en lui permettant de gérer la logique, la testabilité et la maintenabilité de l'application sont considérablement améliorées. Avec ViewModel, Il est possible d'adopter facilement l'architecture Android proposée lors de l'édition 2017 du système Google I / O. Vous pouvez même l'utiliser pour adopter des modèles d'architecture plus sophistiqués, tels que MVP ou MVVM..

Mise en place d'un ViewModel

Il y a deux façons de mettre en œuvre un ViewModel. Le standard consiste à étendre la classe en fournissant un constructeur sans argument. C'est le moyen le plus simple, mais cela ne fonctionne pas bien avec l'injection de dépendance..

classe MainViewModel: ViewModel () init // initialise un comportement fun getData (): LiveData // récupère certaines données remplace l'amusement onCleared () super.onCleared () // appelé avant sa destruction

Pour obtenir un ViewModel construit avec cette technique à partir d'une activité ou d'un fragment, appelez simplement ViewModelProviders.of (FragmentActivity) .get (Classe). Le dernier argument doit contenir le ViewModel classe. Le même ViewModel instance sera récupérée par la vue et contiendra toutes les données pour cette vue.

val viewModel: MainViewModel = ViewModelProviders.of (this) .get (MyViewModel :: class.java)

Notez que, depuis le ViewModel est pris de ViewModelProviders.of méthode, son constructeur ne peut pas recevoir d’arguments. Pour contourner le problème, vous pouvez implémenter une ViewModelProvider.Factory. En fait, c’est la même technique que nous utilisons pour injecter ViewModel.

Injecter un ViewModel

En utilisant DI, les choses deviennent un peu plus compliquées. Vous aurez besoin de mettre en œuvre un ViewModelProvider.Factory. Les étapes suivantes peuvent être utilisées pour injecter un ViewModel en utilisant une dague. le ViewModelFactory est une classe d’utilité qui fournit un ViewModel pour une portée.

@Suppress ("UNCHECKED_CAST") @Singleton, classe ViewModelFactory Constructeur @Inject (créateurs de valeurs privées: Map, @JvmSuppressWildcards Provider>): ViewModelProvider.Factory passer outre le plaisir  create (modelClass: Class): T var créateur: Fournisseur? = creators [modelClass] if (creator == null) for ((clé, valeur) dans creators) if (modelClass.isAssignableFrom (key)) creator = valeur break if (creator == null) jeter IllegalArgumentException ("classe de modèle inconnue" + modelClass) try return creator.get () sous T catch (e: exception) jette RuntimeException (e)

La dague a aussi besoin d'un @Carte clé défini pour ViewModel et un liant pour chaque modèle et pour l'usine dans le module.

// @MapKey @MustBeDocumented @Target (AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) @ kotlin.annotation.Retention () @MapKey Classe d'annotation interne ViewModelKey (valeur valeur: KClass) // ViewModel Module @Module classe abstraite ViewModelsModule // lier chaque ViewModel @Binds @IntoMap @ViewModelKey (MainViewModel :: class) abstract fun bindMainViewModel (mainViewModel: MainViewModel): ViewModel // ViewModel factory binding : ViewModelFactory): ViewModelProvider.Factory

Après cela, suivez les procédures standard de Dagger et vous pourrez créer un ViewModel capable d'injecter des arguments sur son constructeur. Pour créer une nouvelle instance, obtenez le ViewModelFactory et prenez le désiré ViewModel à partir de cela.

// Obtention de la fabrique ViewModel @Inject lateinit var viewModelFactory: ViewModelProvider.Factory // Obtention de ViewModel val viewModel = ViewModelProviders.of (this, viewModelFactory) .get (MainViewModel :: class.java)

Dans notre exemple de projet, vous pouvez examiner de près l’ID à l’aide de Dagger. Je vous ai également fourni un dossier d’exemples dans le référentiel du tutoriel GitHub avec des extraits montrant comment configurer ViewModels sur le système Dagger utilisant Kotlin.

Classe constructeur MainViewModel @Inject (référentiel de valeurs privé: MainRepository): ViewModel (), AnkoLogger //… le code est ici

Conclusion

Jusqu'à présent, notre parcours à travers les nouveaux composants d'architecture Android a été très productif. Cependant, nous avons encore du chemin à parcourir. Dans le prochain tutoriel, nous parlerons de l'impressionnant Données en direct composant, en examinant ses fonctionnalités de base et avancées, et en appliquant ces concepts à notre exemple d'application.

À bientôt! Et en attendant, découvrez quelques-uns de nos autres articles sur le développement d'applications Android.!