Sobes.tech
Junior

Kuidas käivitada koodi paralleelses (mitte peamise) lõimes?

sobes.tech AI

Vastus AI-lt

Android kasutab erinevaid mehhanisme, mis võimaldavad koodi paralleelselt täita, mitte blokeerida peamist (UI) voogu ning säilitada rakenduse reageerimisvõime.

Androidi standardvahendid:

  1. Thread: Uue voolu loomise põhiklass.

    new Thread(new Runnable() {
        @Override
        public void run() {
            // Kood, mis täidetakse paralleelselt
        }
    }).start();
    

    Puudus: Voo käsitsi juhtimine võib põhjustada elutsükli probleeme ja mälulekkeid.

  2. AsyncTask (vana): Lihtsustas paralleelsete voogude tööd ja suhtlust UI vooga.

    private static class MyAsyncTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            // Kood, mis täidetakse taustal
            return null;
        }
    
        @Override
        protected void onPostExecute(Void result) {
            // UI vooga suhtlemine pärast doInBackgroundi
        }
    }
    // Kasutus: new MyAsyncTask().execute();
    

    Miinused: Vananenud, omab piiranguid ja keerukust elutsükli juhtimisel.

  3. Handler ja Looper: võimaldavad luua sõnumtsüklitega vooge.

    HandlerThread handlerThread = new HandlerThread("MyWorkerThread");
    handlerThread.start();
    Handler handler = new Handler(handlerThread.getLooper());
    handler.post(new Runnable() {
        @Override
        public void run() {
            // Kood, mis täidetakse Looperiga voos
        }
    });
    

    Eelis: mugav korduvate ülesannete täitmiseks või asünkroonsete sündmuste töötlemiseks eraldi voos.

  4. ExecutorService / ThreadPoolExecutor: pakuvad sõlmpuule, mis on tõhusam kui iga ülesande jaoks uue Thread loomine.

    ExecutorService executor = Executors.newSingleThreadExecutor(); // Või newCachedThreadPool(), newFixedThreadPool(N)
    executor.execute(new Runnable() {
        @Override
        public void run() {
            // Kood, mis täidetakse sõlmpuust
        }
    });
    // Ära unusta kutsuda executor.shutdown() töö lõppedes
    

    Eelis: haldab voogude loomist ja taaskasutust, vähendab kulusid.

Kaasaegsed lähenemised:

  1. Kotlin Coroutines: kergekaalulised vood, mis pakuvad lihtsamat ja loetavamat viisi asünkroonseks programmeerimiseks.

    import kotlinx.coroutines.*
    
    // Korutina käivitamine voogude basseinil (sarnane taustvoog)
    GlobalScope.launch(Dispatchers.Default) {
        // Kood, mis täidetakse taustal
    }
    
    // Korutina käivitamine IO operatsioonide jaoks
    GlobalScope.launch(Dispatchers.IO) {
        // Kood, mis täidetakse võrgus, failides jms
    }
    
    // Ümberlülitus UI voogu kasutajaliidese uuendamiseks
    GlobalScope.launch(Dispatchers.Default) {
        // Taustarvutused
        withContext(Dispatchers.Main) {
            // UI uuendamine
        }
    }
    

    Eelis: paremini loetav kood, tõhusam ressursside kasutus, lihtne ülesannete tühistamine, struktureeritud konkurents.

  2. RxJava / RxKotlin: reaktiivne programmeerimine, mis põhineb jälgitavatel andmevoogudel.

    import io.reactivex.rxjava3.core.Observable;
    import io.reactivex.rxjava3.schedulers.Schedulers;
    
    Observable.just("Mingisugune tulemus")
        .subscribeOn(Schedulers.io()) // Täitmine IO voos
        .observeOn(AndroidSchedulers.mainThread()) // Jälgimine UI voos
        .subscribe(/* Tulemuse töötlemine */);
    

    Eelis: võimas tööriist asünkroonsete sündmuste ja andmete teisendamiseks, kuid kõrgema sisenemiskünnisega.

WorkManager raamatukogu:

  1. WorkManager: soovitatav Architecture Components komponent garantii tagamiseks taustülesannete täitmisel, isegi kui rakendus on suletud või seade taaskäivitub.
    import androidx.work.*
    import java.util.concurrent.TimeUnit
    
    class MyWorker: Worker(appContext, workerParams) {
        override fun doWork(): Result {
            // Kood, mis täidetakse taustal
            return Result.success() // Või Result.failure(), Result.retry()
        }
    }
    
    // Ülesande päring
    val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
        .setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()) // Valikulised piirangud
        .build()
    
    // Ülesande järjekorda panemine
    WorkManager.getInstance(context).enqueue(workRequest)
    
    Eelis: garantii, et ülesanne täidetakse, toetab piiranguid (võrk, aku), juhtimist tühistamiseks, edasi lükkamist ja kordusi.

Uue meetodi valik sõltub ülesande tüübist, elutsüklist ja usaldusväärsuse nõuetest. Enamik kaasaegseid Android rakendusi soovitab kasutada Kotlin Coroutines või WorkManager.