Middle
Jak organizujesz interakcję między fragmentem a usługą w swojej aplikacji?
sobes.tech AI
Odpowiedź od AI
Wypiszę główne sposoby interakcji między fragmentem a serwisem:
- Serwis powiązany (Bound Service): Fragment jest powiązany z serwisem, uzyskując bezpośredni dostęp do publicznych metod serwisu przez interfejs
IBinder. - Serwis uruchomiony (Started Service): Fragment uruchamia serwis, wysyłając intencje (
Intent) z danymi. W celu zwrotnej informacji serwis może wysyłać intencje broadcast lub używaćResultReceiver. - Intencje broadcast (
BroadcastReceiver): Serwis wysyła intencje broadcast, a fragment je nasłuchuje za pomocąBroadcastReceiver. - Bus zdarzeń (np. GreenDao EventBus, Otto): Używany do wymiany zdarzeń między komponentami przez centralny dispatcher. Serwis publikuje zdarzenia, a fragment się na nie zapisuje.
- LiveData: Fragment może obserwować obiekt
LiveDatawViewModel, który z kolei współdziała z serwisem (np. przez repozytorium lub bezpośredni wywołanie metod powiązanego serwisu).
Przy wyborze metody uwzględniam:
- Typ serwisu (powiązany lub uruchomiony).
- Potrzebę dwukierunkowej interakcji.
- Złożoność przesyłanych danych.
- Cykl życia fragmentu i serwisu.
- Czytelność i utrzymanie kodu.
Przykład powiązania fragmentu z serwisem:
// 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
}
}
Przykład wysyłania intencji broadcast z serwisu:
// Serwis
private fun sendUpdate(data: String) {
Intent("my.app.SERVICE_UPDATE").apply {
putExtra("data", data)
}.also { intent ->
sendBroadcast(intent)
}
}
Przykład odbioru intencji broadcast w fragmencie:
// 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")
// Przetwarzanie danych
}
}
}
}
override fun onResume() {
super.onResume()
IntentFilter("my.app.SERVICE_UPDATE").also { filter ->
requireContext().registerReceiver(receiver, filter)
}
}
override fun onPause() {
super.onPause()
requireContext().unregisterReceiver(receiver)
}