330 votes

La méthode OnActivityResult est dépréciée, quelle est l'alternative ?

J'ai récemment découvert que onActivityResult est déprécié. Que devons-nous faire pour le gérer ?

Une alternative introduite pour cela ?

Image showing code with onActivityResult striked out, indicating deprecation

1 votes

Si je l'enlève une erreur lint est apparue pour ajouter le super appel !

26 votes

Je ne sais pas s'il y a déjà eu une dépréciation qui n'a pas été dépréciée, mais j'ai bon espoir que startActivityForResult . Cette nouvelle façon de faire complique excessivement le code et en réduit la lisibilité.

57 votes

Google est le patron. Mais la façon dont ils continuent à changer les choses en peu de temps est frustrante.

1voto

Rizwan Amjad Points 41

Partage de la solution que j'ai trouvée

Tout d'abord, enregistrez cette activité pour le résultat en utilisant registerForActivityResult Ceci retournera un objet de type ActivityResultLauncher<Intent!> Comme ça,

private val getResult =
        registerForActivityResult(
            ActivityResultContracts.StartActivityForResult()
        ) {
            if (it.resultCode == Activity.RESULT_OK) {
                val value = it.data?.getStringExtra("input")
            }
        }

Maintenant, où que nous voulions lancer l'activité pour le résultat, nous pouvons utiliser getResult.launch(intent)

0 votes

Un exemple simple et facile à suivre - merci !

0voto

Mirza Ahmed Baig Points 342

StartActivityForResult et onActivityResult sont dépréciés dans l'API 30 d'Android 10. Nous avons maintenant une nouvelle façon d'obtenir le résultat en utilisant registerForActivityResult.

resultContract =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            // There are no request codes
            val country = result.data?.getParcelableExtra<Country>("Country")
            showLiveDemoDialogue(country)
        }
    }

et pour lancer l'activité

val intent = Intent(this, CountriesListActivity::class.java)
        resultContract.launch(intent)

mais vous devez vous enregistrer avant d'appeler launch Et lancer où vous voulez. sinon, vous obtiendrez cette exception

attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.

0voto

Ngima Sherpa Points 523

Exemple simple de registerForActivityResult pour StartActivityForResult et RequestMultiplePermissions de l'activité et du fragment [en Kotlin].

Demande d'activité pour un résultat de l'activité

registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { activityResult ->
    if (activityResult.resultCode == Activity.RESULT_OK) {
        //...
    }
}

Vérifiez ActivityResult

Demander des autorisations à l'activité ?

registerForActivityResult(
    ActivityResultContracts.RequestMultiplePermissions()
) {
    //it: Map<String, Boolean>
}

De Fragment ?

Utilisez les mêmes méthodes mais assurez-vous de mettre ces implémentations dans initialization, onAttach(), or onCreate()

0voto

Si vous utilisez l'API de consentement par SMS, utilisez le code suivant (Kotlin) :

resultLauncher.launch( consentIntent
                            )

    var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    if (result.resultCode == Activity.RESULT_OK) {
        // There are no request codes
    //    val data: Intent? = result.data
        val message = result.data?.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
        getOtpFromMessage(message)

    }
}

0voto

Ayman Al-Absi Points 88

J'utilise une extension kotlin pour rendre cela très simple. Ajoutez la fonction d'extension ci-dessous dans votre site Web. Extensions.kt fichier :

fun AppCompatActivity.startForResult(intent: Intent,
    onResult: (resultCode: Int, data: Intent?) -> Unit
) {
    this.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {result ->
        onResult(result.resultCode, result.data)
    }.launch(intent)
}

Maintenant, dans n'importe quelle activité qui hérite de AppCompatActivity, vous pouvez utiliser le code simple ci-dessous :

val i = Intent(this, TargetActivity::class.java)
startForResult(i) { resultCode, data ->
   //put your code here like:
   if (resultCode == RESULT_OK) {
      //your code here...
      }
   }
}

Mise à jour L'implémentation ci-dessus peut causer l'exception ci-dessous : java.lang.IllegalStateException : LifecycleOwner xxxx tente de s'enregistrer alors que l'état actuel est RESUMED. Les LifecycleOwners doivent appeler register avant d'être STARTED.

Ainsi, registerForActivityResult doit être appelé à l'avance, par exemple avant onCreate. Voici la solution alternative.

Ajoutez la fucntion d'extensiton ci-dessous dans votre Extensions.kt fichier :

fun AppCompatActivity.registerForResult(onResult: (resultCode: Int, data: Intent?) -> Unit):
        ActivityResultLauncher<Intent> {
    return this.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        onResult(result.resultCode, result.data)
    }
}

Maintenant, dans n'importe quelle activité qui hérite de AppCompatActivity, vous pouvez utiliser le code simple ci-dessous :

  1. Définir une variable membre de la classe pour chaque action, il faut un résultat

    private val myActionResult = registerForResult { resultCode, data -> //put your code here like: if (resultCode == RESULT_OK) { //your code here... } } }

  2. Lancer l'action

    val i = Intent(this, TargetActivity::class.java) myActionResult.launch(i)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X