🧠 Android Architecture Component Introduction


Note 📝: Cette fiche vous permet de comprendre et d'avoir une rapide rĂ©fĂ©rence sur ce que sont les architectures components. Avec un exercice pratique.

Imaginez le scénario suivant

  1. L'application se lance, votre app doit récupérer depuis le réseau le nom de l'utilisateur
  2. Au lancement, le réseau est lent, et votre interface ne peut se permettre d'afficher juste un écran blanc.
  3. Vous allez devoir surveiller quand la requĂȘte rĂ©seau est terminĂ©e
  4. Lorsque la requĂȘte est terminĂ©, vous devez afficher le nom de l'utilisateur, puis faire disparaitre le loader qui faisait patienter votre utilisateur.
  5. Sauf que, si l'utilisateur fait une rotation du tĂ©lĂ©phone, votre activity est dĂ©truite puis recrĂ©Ă©e (CF schema lifecyle). Vous devez donc gĂ©rer la fuite mĂ©moire qui en dĂ©coule et stopper la requĂȘte rĂ©seau si l'activity passe dans onDestroy(), puis relancer la requĂȘte dans onCreate() uniquement si cela s'est mal passĂ©.
  6. Les donnĂ©es doivent aussi ĂȘtre sauvegardĂ©e dans un Bundle pour ĂȘtre rĂ©affichĂ©es depuis le cache lors d'une rotation ou d'un onPause()
  7. Bonus : Imaginez avoir des fragments par dessus l'activitĂ©, ayant des lifecyle Ă  gĂ©rer -> ☠

Ca donnerait ça (en pseudo code)

var user : User? = null
private lateinit var loader : Loader 
const val USERNAME_BUNDLE_KEY = "username"

var firstLaunch = true


fun onDestroy() {
    NetworkService.cancelAllOperations()
}

fun onResume(){
    if(savedInstanceState != null){
        usernameSaved = savedInstanceState.string(USERNAME_BUNDLE_KEY);
    } else {
        //SSI on a pas déjà les données
        myNetworkRequest().launch(callback = gatheringResultFromNetwork)   
    }
    //Et il faut gérer l'UI etc.
}

//onCreate()
fun onCreate(){
    
    if(savedInstanceState != null && !firstLaunch){
            usernameSaved = savedInstanceState.string(USERNAME_BUNDLE_KEY);
            val textViewUser = findViewById<TextView>(R.id.usernameTextView)
            textViewUser.text = usernameSaved
            }
    
    if(firstLaunch){
        myNetworkRequest().launch(callback = gatheringResultFromNetwork)
    }
    var loader = findViewById<Loader>(R.id.loader)   
    loader.isVisible = true
}

fun gatheringResultFromNetwork() {
    if(result){
        user = result.parseJson.user
        var textView = findViewById<TextView>(R.id.usernameTextView)
        firstLaunch = false
        Globalscope.launch(Dispatchers.Main){
            textView.text = user.name
            loader.isVisible = false
        }
    }
}

fun onSaveInstanceState(Bundle outState) {
    outState.putInt(userName, user.name);
    super.onSaveInstanceState(outState);
}

La mĂȘme chose en utilisant quelques outils des architectures components

//MainActivity.kt
var viewModel: UserViewModel by viewModels()

fun onCreate(){
    //On link notre view model avec la vue XML
    binding.viewModel = viewModel
    
    //On dit que tout action est liée au lifycle de notre activity
    binding.lifecycleOwner = this
}
<!-- main_activity.xml -->
<data>
       <variable
           name="viewModel"
           type="com.example.android.UserViewModel" />     
</data>
<Layout>
    <TextView
       android:id="@+id/usernameTextView"
       ...
       android:text="@{String.valueOf(viewModel.user.name)}"
       ... />
</Layout>

C'est quand mĂȘme plus sympa non ?

SMART

Mais alors qu'est ce qui se passe exactement ?

Simplement on utilise une architecture MVVM qui est de surcroit réactive, avec des composants qui s'imbriquent trÚs bien entre eux :

  • Le DataBinding (UI Components)
  • Les LiveData et ViewModel
  • Le Lifecycle

Une explication simple de la réactivité de cette architecture

Ces composants, utilisés ensemble, vont vous permettre d'avoir peu de code à maintenir, tout en ayant une app bien plus stable.
Pour faire simple, il faut savoir utiliser cela si vous voulez ĂȘtre efficace et rentable dans votre travail de dĂ©veloppeur Android.

Mais mĂȘme plus, il faut que vous soyez Ă  l'affĂ»t des nouveautĂ©s pour constamment optimiser votre workflow et vos pratiques.

Les éléments d'architectures que vous devez comprendre

MVVM

C'est une architecture, tout comme l'est MVC. Une maniĂšre d'organiser votre code, mais aussi de faire communiquer vos composants entre eux.

Il en existe d'autres, mais Google Ă  choisi de pousser cette architecture avec Jetpack.

Lifecycle

C'est une bibliothĂšque qui intĂšgre un certain nombre d'API permettant soit de s'abonner Ă  un cycle de vie, soit de s'approprier un cycle de vie.

En apprendre plus ici

Live Data

Un des composants principaux que vous allez utiliser est le LiveData, ce composant permet de rendre réactif et lifecycle aware n'importe quelle donnée dans votre application.

En apprendre plus ici

ViewModel

En suivant l'architecture MVVM, le viewModel est une piÚce importante de notre code. Il permet d'exposer les sources de données de maniÚre réactive, ainsi une vue peut s'abonner à une ou plusieurs sources de données afin de mettre à jour l'interface.

Le viewModel ne connait pas la vue, mais la vue s'abonne aux données du viewModel.

La classe ViewModel est conçue pour stocker et gérer les données liées à l'interface utilisateur en tenant compte du cycle de vie. La classe ViewModel permet aux données de survivre aux changements de configuration tels que les rotations d'écran.

En apprendre plus ici

DataBinding (Optionnel)

Le binding est une chose, le databinding va plus loin en rendant votre code XML trÚs puissant. Comme en VueJS ou en React vous pourrez directement depuis vos balise XML (Equivalent du HTML en web) appeler des fonctions, des variables et effectuer des opérations complexes.

C'est exactement le mĂȘme principe qui est en place sur Android depuis l'arrivĂ©e de Jetpack et Kotlin.

Donc le databinding, c'est le fait de faire s'abonner la vue XML directement à des valeurs retournée par l'activité ou le fragment.

Ainsi votre logique d'affichage, voire mĂȘme de la logique un peu plus complexe peut s'effectuer directement depuis le XML.

En apprendre plus ici

Pour en faire l'expérience suivez le codelab suivant Data Binding Basics, sinon passez à la suite.

Exercice sur les architectures components

Un peu de code !

Question 1 👉 Qu'est ce qu'un viewModel provider ? Est-ce qu'un view model doit connaitre l'Ă©tat de l'UI ?
Question 2 👉 Qu'est ce qu'une Live Data ? A quoi cela sert ? DĂ©crivez le design pattern Observer avec vos mots
Question 3 👉 Que signifie qu'un composant est lifecyle aware concrùtement ?
Question 4 👉 Faut il exposer un MutableLiveData<> au viewModel ? La vue s'abonne à une LiveData avec quelle instruction ?
(Optionnel) Question 5 👉 Expliquer la diffĂ©rence entre Databinding et Binding. Est-ce que le Databinding est nĂ©cessaire pour travailler sur Android ?
Faites valider les réponses par l'enseignant

🔗 Continuer le cours principal âžĄïž