Kotlin est le langage principal pour le développement Android. Selon Google Android Docs (2025), plus de 95% des nouveaux projets Android utilisent Kotlin. Comprendre les spécificités de Kotlin — data class, sealed class, coroutines et scope functions — est une exigence obligatoire pour un développeur Android.
Points Clés
Kotlin étend les concepts de classes de Java. data class, sealed class, object et companion object — des constructions qui n'existent pas en Java ou sont implémentées différemment.
data class — une classe qui génère automatiquement equals(), hashCode(), toString(), copy() et componentN(). Idéal pour les modèles de données (DTO, Entity). Exigences : au moins un paramètre dans le constructeur primaire, val/var, ne peut pas être open/sealed/inner. sealed class — une classe avec une hiérarchie de sous-classes restreinte. Toutes les sous-classes sont connues à la compilation et déclarées dans le même fichier. L'expression when avec sealed class ne nécessite pas de branche else. sealed interface (Kotlin 1.9+) — identique à sealed class mais permet l'héritage multiple. object — un singleton, déclaré avec le mot-clé object (pas class). Initialisation paresseuse thread-safe. companion object — membres statiques d'une classe. A un nom (Companion par défaut). Peut implémenter des interfaces et avoir des extension functions.
| Type | Description | Utilisation |
|---|---|---|
| data class | Génération automatique de equals, hashCode, toString, copy | Modèles de données, DTO, Entity |
| sealed class | Hiérarchie restreinte, vérification when | États, Résultat, UI State |
| sealed interface | sealed class + héritage multiple | Événements, Actions (Kotlin 1.9+) |
| object | Singleton (déclaratif) | Factory, Utility, Constantes |
| companion object | Membres statiques de classe | Factory Method, constantes statiques |
| enum class | Énumération avec constantes | États avec ensemble fixe |
data class — pour 90% des modèles. sealed class — pour UI State et Résultat. object — pour les singletons. IT Sectr recommande sealed class pour tous les états d'écran (Loading, Success, Error).
Sealed class — un outil puissant pour modéliser les états. Exemple : UiState<T> avec sous-classes Loading, Success(data: T), Error(message: String). L'expression when garantit le traitement de tous les états. Sealed interface — pour les événements et actions où une implémentation multiple est nécessaire. Value class (Kotlin 1.5+) — un wrapper pour une valeur unique sans overhead. Utilisé pour les identifiants type-safe : @JvmInline value class UserId(val id: String).
Extension Function — ajouter une méthode à une classe existante sans héritage. fun String.isEmail(): Boolean. Extension Property — même chose pour les propriétés (sans backing field). Inline Function — insertion du corps de la fonction au site d'appel — sans overhead d'appel. Utilisé pour les higher-order functions avec lambdas. Higher-Order Function — une fonction qui prend ou retourne une autre fonction. Scope Functions — cinq fonctions pour travailler avec le contexte d'un objet : let, run, with, apply, also.
let — contexte it, retourne le résultat de la lambda. Utilisé pour les appels null-safe (?.let {}). apply — contexte this, retourne le contexte. Pour la configuration d'objet. run — contexte this, retourne le résultat de la lambda. Pour les calculs avec contexte. also — contexte it, retourne le contexte. Pour les effets secondaires (logging). with — n'est pas une extension, contexte this, retourne le résultat de la lambda. Pour un groupe d'opérations sur un objet. Lambda — fonction anonyme. Destructuring Declaration — décompression de data class en variables : val (name, age) = person.
Inline function avec reified — la seule façon de préserver un type générique dans la JVM. Utilisé pour : les builders type-safe (Gson.fromJson<T>()), la vérification de types (is T), l'obtention de la classe (T::class). Crossinline et Noinline — modificateurs pour les paramètres lambda dans les fonctions inline. crossinline — interdit le non-local return, noinline — interdit l'inlining d'une lambda spécifique. IT Sectr recommande inline + reified uniquement lors du travail avec les types ; pour les fonctions higher-order classiques, inline peut augmenter la taille du bytecode.
Coroutines — des threads légers pour la programmation asynchrone. Ne bloquent pas le thread — se suspendent. suspend function — une fonction qui peut être suspendue sans bloquer le thread. Ne peut être appelée que depuis une coroutine ou une autre suspend function.
CoroutineScope — une portée pour les coroutines. Contient CoroutineContext (Job + Dispatcher). lifecycleScope — pour Activity/Fragment (Lifecycle-aware). viewModelScope — pour ViewModel (annulation automatique à onCleared()). GlobalScope — portée globale (déconseillé en production — fuites mémoire). Dispatchers : Dispatchers.Main (UI), Dispatchers.IO (réseau/disque), Dispatchers.Default (CPU-intensive), Dispatchers.Unconfined (déconseillé). launch — démarre une coroutine : Job. async — démarre avec résultat : Deferred<T>. runBlocking — pont bloquant. withContext — change de Dispatcher dans une suspend function.
// Exemple de coroutines : chargement de données dans ViewModel
class MainViewModel : ViewModel() {
private val _state = MutableStateFlow<UiState>(UiState.Loading)
val state: StateFlow<UiState> = _state.asStateFlow()
fun loadData() {
viewModelScope.launch {
_state.value = UiState.Loading
try {
val data = withContext(Dispatchers.IO) {
repository.fetchData()
}
_state.value = UiState.Success(data)
} catch (e: Exception) {
_state.value = UiState.Error(e.message)
}
}
}
}
// Requêtes parallèles avec async
suspend fun loadCombinedData(): CombinedData = coroutineScope {
val users = async(Dispatchers.IO) { api.getUsers() }
val posts = async(Dispatchers.IO) { api.getPosts() }
CombinedData(users.await(), posts.await())
}viewModelScope.launch — lancement standard de coroutine dans ViewModel. withContext(Dispatchers.IO) — basculement vers le thread IO pour une requête réseau. Dispatchers déterminent sur quel pool de threads la coroutine s'exécute. IT Sectr recommande viewModelScope pour ViewModel et lifecycleScope pour Activity/Fragment.
reified — un modificateur de type dans les fonctions inline. Permet d'utiliser le type : T::class, is T, as T. Sans reified, les génériques dans la JVM sont effacés (type erasure). inline fun + reified — une combinaison puissante pour des APIs type-safe. Destructuring Declaration — val (x, y) = point. Fonctionne pour data class et les types avec componentN(). typealias — alias de type : typealias Callback = (String) -> Unit. lateinit — initialisation différée de var (pour l'injection de dépendances). Non thread-safe. lazy — initialisation paresseuse de val (thread-safe par défaut). lazy(LazyThreadSafetyMode.NONE) — sans synchronisation. Extension function et Extension property — ajouter des fonctionnalités sans héritage. Kotlin est un langage où les extension functions résolvent 90% des tâches utilitaires.
Delegated Properties — déléguer getter/setter à un autre objet. Délégués standard : lazy, observable, vetoable, map. Délégué personnalisé via les opérateurs getValue/setValue. by — mot-clé de délégation : val name by lazy { loadName() }. Les propriétés déléguées sont la base des délégués ViewModel (by viewModels()). IT Sectr recommande lazy pour l'initialisation différée et Delegates.observable pour observer les changements.
| Fonctionnalité | Description | Exemple |
|---|---|---|
| reified | Préservation du type générique dans inline | inline fun <reified T> parse(): T |
| destructuring | Décompression de data class | val (name, age) = person |
| typealias | Alias de type | typealias Orders = List<Order> |
| lateinit | Initialisation différée de var | lateinit var adapter: Adapter |
| lazy | Initialisation paresseuse de val | val config by lazy { load() } |
| delegated | Délégation de propriétés | var x by Delegates.observable(0) |
reified — pour des APIs type-safe. lazy — pour le chargement différé. delegated properties — pour réutiliser la logique des propriétés. IT Sectr recommande de maîtriser toutes ces fonctionnalités pour un développement efficace en Kotlin.
Flow — flux de données asynchrone froid en Kotlin. Émet des valeurs à la demande du collecteur. StateFlow — Flow chaud avec une seule valeur actuelle. Utilisé dans ViewModel pour UI State. SharedFlow — Flow chaud pour les événements (événements uniques). flowOf, asFlow — création de Flow à partir de collections. catch, retry, debounce — opérateurs. stateIn, shareIn — conversion de Flow froid en chaud. IT Sectr recommande StateFlow pour UI State et SharedFlow pour les événements (Snackbar, navigation).
class SearchViewModel : ViewModel() {
private val _query = MutableStateFlow("")
val suggestions: StateFlow<List<String>> = _query
.debounce(300)
.filter { it.length >= 2 }
.flatMapLatest { repository.search(it) }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
fun onQueryChanged(query: String) {
_query.value = query
}
}kotlinx.serialization — bibliothèque Kotlin pour la sérialisation JSON. @Serializable — annotation. @SerialName — nom de champ personnalisé. Supporte : JSON, CBOR, ProtoBuf. Parcelize — @Parcelize pour Android Parcelable (sans implémentation manuelle). Gson vs Moshi vs kotlinx : kotlinx.serialization — Kotlin-first, compile-safe, sans reflection. Moshi — annotations + codegen. IT Sectr recommande kotlinx.serialization pour les nouveaux projets et Moshi pour les existants.
@Serializable
data class ApiResponse<T>(
val success: Boolean,
@SerialName("data") val data: T? = null,
val error: String? = null
)
@Serializable
data class User(
val id: Int,
val name: String,
val email: String
)
// Désérialisation
val json = Json { ignoreUnknownKeys = true }
val response = json.decodeFromString<ApiResponse<List<User>>>(jsonString)
println("Users: ${response.data?.size ?: 0}")Foire Aux Questions
data class — pour les données (génération automatique de equals/hashCode/copy). sealed class — pour la hiérarchie de types (vérification dans when). sealed interface — pareil avec héritage multiple.
let, run, with, apply, also. Se différencient par le contexte (it vs this) et la valeur de retour (result vs context). let — null safety, apply — configuration, also — effets secondaires.
CoroutineScope — une portée pour les coroutines. lifecycleScope — pour Activity, viewModelScope — pour ViewModel. GlobalScope — déconseillé.
reified — préservation du type dans les fonctions inline. Permet T::class et is T. Fonctionne uniquement avec les fonctions inline.
launch — sans résultat. async — avec résultat (Deferred). runBlocking — pont bloquant pour main/test. withContext — changement de Dispatcher.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.