Sobes.tech
Junior

Comment exécuter du code dans un thread parallèle (non principal) ?

sobes.tech IA

Réponse de l'IA

Pour l'exécution parallèle du code sur Android, divers mécanismes sont utilisés pour ne pas bloquer le thread principal (UI) et maintenir la réactivité de l'application.

Moyens intégrés d'Android :

  1. Thread : Classe de base pour créer un nouveau thread.

    new Thread(new Runnable() {
        @Override
        public void run() {
            // Code à exécuter dans un thread parallèle
        }
    }).start();
    

    Inconvénient : La gestion manuelle des threads peut entraîner des problèmes avec le cycle de vie et des fuites de mémoire.

  2. AsyncTask (Obsolète) : Facilita la gestion des threads parallèles et l'interaction avec le thread UI.

    private static class MyAsyncTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            // Code à exécuter en arrière-plan
            return null;
        }
    
        @Override
        protected void onPostExecute(Void result) {
            // Travail avec le thread UI après doInBackground
        }
    }
    // Utilisation : new MyAsyncTask().execute();
    

    Inconvénients : Obsolète, avec des limitations et des difficultés dans la gestion du cycle de vie.

  3. Handler et Looper : Permettent de créer des threads avec des boucles de traitement de messages.

    HandlerThread handlerThread = new HandlerThread("MyWorkerThread");
    handlerThread.start();
    Handler handler = new Handler(handlerThread.getLooper());
    handler.post(new Runnable() {
        @Override
        public void run() {
            // Code à exécuter dans le thread avec Looper
        }
    });
    

    Avantage : Utile pour les tâches répétitives ou la gestion d'événements asynchrones dans un thread séparé.

  4. ExecutorService / ThreadPoolExecutor : Fournissent des pools de threads, plus efficaces que de créer un nouveau Thread pour chaque tâche.

    ExecutorService executor = Executors.newSingleThreadExecutor(); // Ou newCachedThreadPool(), newFixedThreadPool(N)
    executor.execute(new Runnable() {
        @Override
        public void run() {
            // Code à exécuter dans un thread du pool
        }
    });
    // N'oubliez pas d'appeler executor.shutdown() à la fin
    

    Avantages : Gèrent la création et la réutilisation des threads, réduisant les coûts.

Approches modernes :

  1. Kotlin Coroutines : Threads légers offrant une manière plus simple et lisible de programmation asynchrone.

    import kotlinx.coroutines.*
    
    // Lancer une coroutine dans un pool de threads (similaire à un thread de fond)
    GlobalScope.launch(Dispatchers.Default) {
        // Code à exécuter en arrière-plan
    }
    
    // Lancer une coroutine pour les opérations IO
    GlobalScope.launch(Dispatchers.IO) {
        // Code pour effectuer des opérations IO (réseau, fichiers, etc.)
    }
    
    // Passer au thread UI pour mettre à jour l'interface utilisateur
    GlobalScope.launch(Dispatchers.Default) {
        // Calculs en arrière-plan
        withContext(Dispatchers.Main) {
            // Mise à jour de l'UI
        }
    }
    

    Avantages : Meilleure lisibilité du code, utilisation plus efficace des ressources, gestion simplifiée de l'annulation des tâches, concurrence structurée.

  2. RxJava / RxKotlin : Programmation réactive basée sur des flux de données observables.

    import io.reactivex.rxjava3.core.Observable;
    import io.reactivex.rxjava3.schedulers.Schedulers;
    
    Observable.just("Un certain résultat")
        .subscribeOn(Schedulers.io()) // Exécuter dans le thread IO
        .observeOn(AndroidSchedulers.mainThread()) // Observer dans le thread UI
        .subscribe(/* Traitement du résultat */);
    

    Avantages : Outil puissant pour gérer des événements asynchrones et transformer des données, mais avec une courbe d'apprentissage plus élevée.

Bibliothèque WorkManager :

  1. WorkManager : Composant recommandé d'Architecture Components pour garantir l'exécution fiable des tâches en arrière-plan, même si l'application est fermée ou si l'appareil est redémarré.
    import androidx.work.*
    import java.util.concurrent.TimeUnit
    
    class MyWorker(appContext: Context, workerParams: WorkerParameters): Worker(appContext, workerParams) {
        override fun doWork(): Result {
            // Code pour exécuter la tâche en arrière-plan
            return Result.success() // Ou Result.failure(), Result.retry()
        }
    }
    
    // Créer une requête pour exécuter la tâche
    val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
        .setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()) // Contraintes optionnelles
        .build()
    
    // Mettre la tâche en file d'attente
    WorkManager.getInstance(context).enqueue(workRequest)
    
    Avantages : Exécution garantie, supporte les contraintes (type de réseau, batterie), gestion des annulations, exécutions différées et répétitions.

Le choix de la méthode spécifique pour exécuter du code dans un thread parallèle dépend du type de tâche, de son cycle de vie et des exigences de fiabilité. Pour la plupart des applications Android modernes, il est recommandé d'utiliser Kotlin Coroutines ou WorkManager.