Sobes.tech
Middle

Comment organisez-vous l'interaction entre le fragment et le service dans votre application?

sobes.tech IA

Réponse de l'IA

Je vais énumérer les principales méthodes d'interaction entre un fragment et un service:

  • Service lié (Bound Service): Le fragment se lie au service, accédant directement aux méthodes publiques du service via l'interface IBinder.
  • Service démarré (Started Service): Le fragment démarre le service en envoyant des intentions (Intent) avec des données. Pour la rétroaction, le service peut envoyer des intentions broadcast ou utiliser ResultReceiver.
  • Intentions broadcast (BroadcastReceiver): Le service envoie des intentions broadcast, et le fragment les écoute via BroadcastReceiver.
  • Bus d'événements (par exemple, GreenDao EventBus, Otto): Utilisés pour échanger des événements entre composants via un dispatcher central. Le service publie des événements, et le fragment s'y abonne.
  • LiveData: Le fragment peut observer un objet LiveData dans ViewModel, qui interagit à son tour avec le service (par exemple, via un dépôt ou un appel direct aux méthodes du service lié).

Lors du choix de la méthode, je considère:

  • Type de service (lié ou démarré).
  • Nécessité d'une interaction bidirectionnelle.
  • Complexité des données transmises.
  • Cycle de vie du fragment et du service.
  • Lisibilité et maintenabilité du code.

Exemple de liaison d'un fragment à un service:

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

Exemple d'envoi d'une intention broadcast depuis le service:

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

Exemple de réception d'une intention broadcast dans un fragment:

// 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")
                // Traiter les données
            }
        }
    }
}

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

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