Questions d'entretien Kotlin/Android
1. Quels sont les avantages de Kotlin par rapport à Java pour Android ?
Kotlin offre : null safety (types nullable explicites avec ?), data classes (equals, hashCode, copy generes), extensions functions (ajouter des méthodes aux classes existantes), coroutines (programmation asynchrone simplifiée), scope functions (let, apply, run, with, also), smart casts (cast automatique après vérification de type), syntaxe plus concise (moins de boilerplate), et interopérabilité totale avec Java. Google recommande Kotlin comme langage principal pour Android depuis 2019.
2. Expliquez les coroutines Kotlin et leur utilité sur Android.
Les coroutines sont des threads legers pour la programmation asynchrone. Elles permettent d'écrire du code asynchrone de manière sequentielle avec suspend functions. Sur Android, elles evitent de bloquer le thread principal (UI thread) lors des opérations longues (réseau, base de données). Concepts clés : CoroutineScope (gere le cycle de vie), Dispatchers (Main pour l'UI, IO pour les I/O, Default pour le CPU), launch (lance sans résultat), async/await (lance avec résultat). ViewModelScope et lifecycleScope annulent automatiquement les coroutines.
3. Qu'est-ce que Jetpack Compose et comment se compare-t-il aux Views XML ?
Jetpack Compose est le toolkit UI déclaratif de Google pour Android. Au lieu de définir l'interface en XML et de la manipuler imperativement, vous décrivez l'UI dans des fonctions @Composable en Kotlin. Compose gere automatiquement les mises à jour via la recomposition (quand l'état change, seules les parties affectees sont recalculees). Avantages : moins de code, aperçu en temps réel, API Kotlin idiomatique. Les Views XML restent supportees et interoperables avec Compose.
4. Expliquez la gestion de l'état dans Jetpack Compose.
L'état dans Compose suit le principe de state hoisting : remonter l'état au composant parent et passer des callbacks vers les enfants. Types : remember (survit aux recompositions mais pas aux changements de configuration), rememberSaveable (survit aux changements de configuration), collectAsState (observe un Flow/StateFlow), mutableStateOf (état observable par Compose). Pour l'état complexe, utilisez un ViewModel avec StateFlow ou State.
5. Comment fonctionne la navigation dans une application Android ?
La bibliothèque Navigation Compose gere la navigation entre les écrans. Définissez un NavHost avec un NavController et des routes (strings ou objets type-safe depuis Navigation 2.8). Chaque écran est un composable dans le NavHost. La navigation gere automatiquement le back stack, les arguments de route, les deep links et les animations de transition. Pour les applications complexes, utilisez des nested navigation graphs pour organiser les flux par fonctionnalité.
6. Qu'est-ce que l'architecture MVVM recommandee par Google ?
Google recommande l'architecture MVVM avec Clean Architecture : UI Layer (composables + ViewModel), Domain Layer (use cases optionnels), Data Layer (repositories + data sources). Le ViewModel expose un StateFlow ou State à l'UI. Le Repository abstrait les sources de données (API, base locale). Les Use Cases encapsulent la logique métier. Le flux de données est unidirectionnel : l'UI envoie des events au ViewModel qui met à jour le state.
7. Comment persister les données localement sur Android ?
Room : ORM SQLite avec vérification des requêtes à la compilation. Définissez des entités (@Entity), des DAO (@Dao avec des requêtes SQL) et une database. DataStore : remplacement de SharedPreferences pour les préférences (Préférences DataStore) ou les données typées (Proto DataStore). SharedPreferences (legacy) : paires cle-valeur simples. Encrypted SharedPreferences : pour les données sensibles non-critiques. SQLite direct : rarement nécessaire avec Room.
8. Expliquez le cycle de vie d'une Activity et d'un Fragment.
Activity : onCreate (création) -> onStart (visible) -> onResume (interactive) -> onPause (partiellement masquee) -> onStop (invisible) -> onDestroy (detruite). Fragment : mêmes callbacks plus onCreateView, onViewCreated, onDestroyView. Les changements de configuration (rotation) detruisent et recreent l'Activity. Le ViewModel survit à ces changements. Avec Compose, le cycle de vie est simplifie : les composables suivent le cycle de vie de leur ComponentActivity.
9. Comment gérer les appels réseau sur Android ?
Retrofit est le standard pour les appels HTTP. Définissez une interface avec des annotations (@GET, @POST, @Path, @Body). Retrofit serialise/deserialise avec Moshi ou Kotlinx Serialization. Utilisez les coroutines (fonctions suspend) pour les appels asynchrones. Implémentez un Repository qui combine les données distantes et locales (cache Room). Gérez les erreurs avec des sealed classes (Result ou un type custom Success/Error/Loading).
10. Comment tester une application Android ?
Tests unitaires (JVM) : testez les ViewModels, Repositories et Use Cases avec JUnit et Mockk. Tests d'instrumentation (appareil/emulateur) : testez l'UI avec Compose Testing (createComposeRule, onNodeWithText, performClick). Tests d'intégration : testez Room avec une base en mémoire. Tests end-to-end : Espresso ou Compose Testing pour les flux complets. Utilisez Turbine pour tester les Flows et Hilt pour l'injection de dépendances dans les tests.