Sobes.tech
Middle

Ako organizujete interakciu medzi fragmentom a službou vo vašej aplikácii?

sobes.tech AI

Odpoveď od AI

Hlavné spôsoby interakcie medzi fragmentom a službou sú:

  • Viazaná služba (Bound Service): Fragment sa viaže na službu a získava priamy prístup k verejným metódam cez rozhranie IBinder.
  • Spustená služba (Started Service): Fragment spúšťa službu odoslaním zámerov (Intent) s údajmi. Na spätnú väzbu môže služba posielať vysielacie závery alebo používať ResultReceiver.
  • Vysielacie závery (BroadcastReceiver): Služba odosiela vysielacie závery, ktoré fragment počúva pomocou BroadcastReceiver.
  • Esemény Bus (napríklad GreenDao EventBus, Otto): Používa sa na výmenu udalostí medzi komponentami cez centrálny správca. Služba publikuje udalosti a fragment sa na ne prihlasuje.
  • LiveData: Fragment môže sledovať objekt LiveData v ViewModel, ktorý na oplátku komunikuje so službou (napríklad cez repozitár alebo priamy volanie metód pripojenej služby).

Pri výbere spôsobu zohľadňujem:

  • Typ služby (viazaná alebo spustená).
  • Potrebu obojsmernej komunikácie.
  • Složitost prenosu dát.
  • Životný cyklus fragmentu a služby.
  • Čitateľnosť a udržiavateľnosť kódu.

Príklad viazania fragmentu ku službe:

// Fragment
private lateinit var myService: MyService
private var isBound = false

private val connection = object : ServiceConnection {
    override fun onServiceConnected(className: ComponentName, service: IBinder) {
        val binder = service as MyService.LocalBinder
        myService = binder.getService()
        isBound = true
    }

    override fun onServiceDisconnected(arg0: ComponentName) {
        isBound = false
    }
}

override fun onStart() {
    super.onStart()
    Intent(requireContext(), MyService::class.java).also { intent ->
        requireContext().bindService(intent, connection, Context.BIND_AUTO_CREATE)
    }
}

override fun onStop() {
    super.onStop()
    if (isBound) {
        requireContext().unbindService(connection)
        isBound = false
    }
}

Príklad odoslania vysielacieho zámeru zo služby:

// Služba
private fun sendUpdate(data: String) {
    Intent("my.app.SERVICE_UPDATE").apply {
        putExtra("data", data)
    }.also { intent ->
        sendBroadcast(intent)
    }
}

Príklad prijatia vysielacieho zámeru vo fragmente:

// Fragment
private val receiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        when (intent?.action) {
            "my.app.SERVICE_UPDATE" -> {
                val data = intent.getStringExtra("data")
                // Spracovanie dát
            }
        }
    }
}

override fun onResume() {
    super.onResume()
    IntentFilter("my.app.SERVICE_UPDATE").also { filter ->
        requireContext().registerReceiver(receiver, filter)
    }
}

override fun onPause() {
    super.onPause()
    requireContext().unregisterReceiver(receiver)
}