Sobes.tech
Middle

Kako organizujete interakciju između fragmenta i usluge u vašoj aplikaciji?

sobes.tech АИ

Одговор од АИ

Главни начини за интеракцију између фрагмента и сервиса су:

  • Бодовани сервис (Bound Service): Фрагмент се везује за сервис и добија директан приступ јавним методама преко интерфејса IBinder.
  • Покренути сервис (Started Service): Фрагмент покреће сервис слањем намера (Intent) са подацима. За повратну информацију, сервис може слати широковасшне намере или користити ResultReceiver.
  • Широковасшне намере (BroadcastReceiver): Сервис шаље широковасшне намере, а фрагмент их слуша помоћу BroadcastReceiver.
  • Евент Бус (нпр. GreenDao EventBus, Otto): Користи се за размену догађаја између компоненти преко централизованог управника. Сервис објављује догађаје, а фрагмент се на њих пријављује.
  • LiveData: Фрагмент може посматрати објекат LiveData у ViewModel, који, с друге стране, комуницира са сервисом (нпр. преко репозиторијума или директним позивом метода повезаног сервиса).

При избору начина узимам у обзир:

  • Тип сервиса (везани или покренути).
  • Потребу за двосмерном интеракцијом.
  • Комплексност преносних података.
  • Животни циклус фрагмента и сервиса.
  • читљивост и одрживост кода.

Пример везивања фрагмента за сервис:

// Фрагмент
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
    }
}

Пример слања широковасшне намере из сервиса:

// Сервис
private fun sendUpdate(data: String) {
    Intent("my.app.SERVICE_UPDATE").apply {
        putExtra("data", data)
    }.also { intent ->
        sendBroadcast(intent)
    }
}

Пример прихвата широковасшне намере у фрагменту:

// Фрагмент
private val receiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        when (intent?.action) {
            "my.app.SERVICE_UPDATE" -> {
                val data = intent.getStringExtra("data")
                // Обрада података
            }
        }
    }
}

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

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