Sobes.tech
Junior

Kaip veikia pagrindinis srautas Android?

sobes.tech AI

Atsakymas iš AI

Pagrindinis srautas (Main Thread) Android'e, taip pat žinomas kaip UI Thread, yra vienintelis srautas, kuris:

  • Apdoroja visus naudotojo sąsajos įvykius (mygtukų paspaudimus, slinkimus).
  • Nupiečia elementus ekrane.
  • Vykdo komponentų gyvavimo ciklo kodą (Activity, Fragment).

Kartu pradėjus programą, Android sukuria pagrindinį srautą. Visi naudotojo sąsajos komponentai kuriami ir atnaujinami tik šiame sraute.

Pagrindinės sąvokos:

  • Event Loop: Pagrindinis srautas veikia cikle, nuolat ištraukdamas žinutes (UI įvykius, piešimo užduotis) iš MessageQueue eilės ir siunčia jas atitinkamiems apdorotojams (Handler).
  • Looper: Looper objektas yra susijęs su srautu ir valdo šį žinučių apdorojimo ciklą.
  • Handler: Handler objektas leidžia siųsti ir apdoroti Message ir Runnable objektus susijusiame MessageQueue sraute, kur jis buvo sukurtas. Paprastai Handler kuriamas pagrindiniame sraute, kad galėtų sąveikauti su UI iš kitų srautų.

Problemos:

  • ANR (Application Not Responding): Jei ilgalaikė operacija vyksta pagrindiniame sraute, jis užstringa, neapdoroja UI įvykių ir nebraižo ekrano. Tai sukelia programos užšalimą ir ANR dialogą. Tipiškai, ilgis, kuris sukelia ANR pagrindiniame sraute dirbant su UI, yra 5 sekundės.

Sprendimai:

  • Ilgalaikių operacijų (tinklo užklausų, duomenų bazės darbo, sudėtingų skaičiavimų) vykdymas fondo srautose.
  • Naudojant tarpsrautinius bendravimo mechanizmus UI atnaujinimui iš foninių srautų (pvz., Handler, AsyncTask, Coroutines).
// Pavyzdys, kaip naudoti Handler UI atnaujinimui iš foninio srauto
Handler mainHandler = new Handler(Looper.getMainLooper());

new Thread(new Runnable() {
    @Override
    public void run() {
        // Vykdyti ilgą operaciją foniniame sraute
        // ...

        // Siųsti užduotį UI atnaujinimui į pagrindinį srautą
        mainHandler.post(new Runnable() {
            @Override
            public void run() {
                // UI atnaujinimas pagrindiniame sraute
                // ...
            }
        });
    }
}).start();
// Pavyzdys, kaip naudoti korutinas UI atnaujinimui iš foninio srauto
import kotlinx.coroutines.*

fun fetchDataAndUpdateUI() {
    CoroutineScope(Dispatchers.IO).launch {
        // Vykdyti ilgą operaciją
        val data = fetchDataFromServer()

        // Perjungti į pagrindinį srautą UI atnaujinimui
        withContext(Dispatchers.Main) {
            updateUI(data)
        }
    }
}