Sobes.tech
Junior

Kā izpildīt kodu paralēlajā (ne galvenajā) pavedienā?

sobes.tech AI

Atbilde no AI

Android izmanto dažādus mehānismus, kas ļauj paralēli izpildīt kodu, neblokējot galveno (UI) plūsmu un saglabājot lietotnes atsaucību.

Standarta Android līdzekļi:

  1. Thread: Jauna pavediena izveides pamatklase.

    new Thread(new Runnable() {
        @Override
        public void run() {
            // Kods, kas tiek izpildīts paralēlajā pavedienā
        }
    }).start();
    

    Trūkums: Rokas vadība pavedieniem var novest pie dzīves cikla problēmām un atmiņas noplūdēm.

  2. AsyncTask (novecojis): Vienkāršoja darbu ar paralēlajiem pavedieniem un UI plūsmas mijiedarbību.

    private static class MyAsyncTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            // Kods, kas tiek izpildīts fonā
            return null;
        }
    
        @Override
        protected void onPostExecute(Void result) {
            // Darbs ar UI plūsmu pēc doInBackground pabeigšanas
        }
    }
    // Lietošana: new MyAsyncTask().execute();
    

    Trūkumi: Novecojis, ir ierobežojumi un sarežģījumi dzīves cikla pārvaldībā.

  3. Handler un Looper: ļauj izveidot pavedienus ar ziņu apstrādes cikliem.

    HandlerThread handlerThread = new HandlerThread("MyWorkerThread");
    handlerThread.start();
    Handler handler = new Handler(handlerThread.getLooper());
    handler.post(new Runnable() {
        @Override
        public void run() {
            // Kods, kas tiek izpildīts ar Looper plūsmu
        }
    });
    

    Priekšrocība: ērti atkārtotu uzdevumu izpildei vai asinhronu notikumu apstrādei atsevišķā pavedienā.

  4. ExecutorService / ThreadPoolExecutor: nodrošina pavedienu baseinus, kas ir efektīvāki nekā jauna Thread izveide katrai uzdevumam.

    ExecutorService executor = Executors.newSingleThreadExecutor(); // vai newCachedThreadPool(), newFixedThreadPool(N)
    executor.execute(new Runnable() {
        @Override
        public void run() {
            // Kods, kas tiek izpildīts no baseina pavediena
        }
    });
    // Neaizmirstiet izsaukt executor.shutdown() pēc darba pabeigšanas
    

    Priekšrocības: pārvalda pavedienu izveidi un atkārtotu izmantošanu, samazina izmaksas.

Mūsdienu pieejas:

  1. Kotlin Coroutines: viegli srauti, kas nodrošina vienkāršāku un lasāmāku veidu asinhronai programmēšanai.

    import kotlinx.coroutines.*
    
    // Korutinas palaišana sērijas (fonā)
    GlobalScope.launch(Dispatchers.Default) {
        // Kods, kas tiek izpildīts fonā
    }
    
    // Korutinas palaišana ar IO operācijām
    GlobalScope.launch(Dispatchers.IO) {
        // Kods, kas tiek izpildīts ar tīkla, failu u.c. operācijām
    }
    
    // Pārsēšana uz UI plūsmu, lai atjauninātu lietotāja saskarni
    GlobalScope.launch(Dispatchers.Default) {
        // Fona aprēķini
        withContext(Dispatchers.Main) {
            // UI atjaunināšana
        }
    }
    

    Priekšrocības: uzlabota koda lasāmība, efektīvāka resursu izmantošana, vienkārša uzdevumu atcelšana, strukturēta konkurētspēja.

  2. RxJava / RxKotlin: reaktīva programmēšana, balstīta uz novērojamiem datu plūsmām.

    import io.reactivex.rxjava3.core.Observable;
    import io.reactivex.rxjava3.schedulers.Schedulers;
    
    Observable.just("Kāds rezultāts")
        .subscribeOn(Schedulers.io()) // Izpilde IO plūsmā
        .observeOn(AndroidSchedulers.mainThread()) // Novērošana UI plūsmā
        .subscribe(/* Rezultāta apstrāde */);
    

    Priekšrocības: jaudīgs rīks asinhronām notikumu apstrādei un datu pārveidošanai, bet ar augstāku ieejas slieksni.

WorkManager bibliotēka:

  1. WorkManager: ieteicamā Architecture Components sastāvdaļa garantētai fonu uzdevumu izpildei, pat ja lietotne ir aizvērta vai ierīce ir pārstartēta.
    import androidx.work.*
    import java.util.concurrent.TimeUnit
    
    class MyWorker: Worker(appContext, workerParams) {
        override fun doWork(): Result {
            // Kods, kas tiek izpildīts fonā
            return Result.success() // vai Result.failure(), Result.retry()
        }
    }
    
    // Uzdevuma pieprasījuma izveide
    val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
        .setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()) // Pēc izvēles ierobežojumi
        .build()
    
    // Uzdevuma pievienošana rindai
    WorkManager.getInstance(context).enqueue(workRequest)
    
    Priekšrocības: garantēta izpilde, atbalsta ierobežojumus (tīkla tips, akumulatora uzlāde), pārvaldība atcelšanai, atliktai izpildei un atkārtojumiem.

Konkrēta metodes izvēle ir atkarīga no uzdevuma veida, tā dzīves cikla un uzticamības prasībām. Lielākajai daļai mūsdienu Android lietojumprogrammu ieteicams izmantot Kotlin Coroutines vai WorkManager.