Sobes.tech
Middle

Como você organiza a interação entre o fragmento e o serviço na sua aplicação?

sobes.tech IA

Resposta da IA

Vou enumerar as principais formas de interação entre um fragmento e um serviço:

  • Serviço vinculado (Bound Service): O fragmento liga-se ao serviço, obtendo acesso direto aos métodos públicos do serviço através da interface IBinder.
  • Serviço iniciado (Started Service): O fragmento inicia o serviço enviando intenções (Intent) com dados. Para feedback, o serviço pode enviar intenções broadcast ou usar ResultReceiver.
  • Intenções broadcast (BroadcastReceiver): O serviço envia intenções broadcast, e o fragmento as escuta usando BroadcastReceiver.
  • Bus de eventos (por exemplo, GreenDao EventBus, Otto): São usados para trocar eventos entre componentes através de um despachante central. O serviço publica eventos, e o fragmento inscreve-se neles.
  • LiveData: O fragmento pode observar um objeto LiveData no ViewModel, que por sua vez interage com o serviço (por exemplo, através de um repositório ou chamada direta aos métodos do serviço vinculado).

Ao escolher o método, considero:

  • Tipo de serviço (vinculado ou iniciado).
  • Necessidade de interação bidirecional.
  • Complexidade dos dados transmitidos.
  • Ciclo de vida do fragmento e do serviço.
  • Legibilidade e manutenção do código.

Exemplo de ligação de um fragmento a um serviço:

// 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
    }
}

Exemplo de envio de intenção broadcast do serviço:

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

Exemplo de recepção de intenção broadcast no fragmento:

// 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")
                // Processar dados
            }
        }
    }
}

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

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