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 ?
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)
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.
registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { activityResult ->
if (activityResult.resultCode == Activity.RESULT_OK) {
//...
}
}
Demander des autorisations à l'activité ?
registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) {
//it: Map<String, Boolean>
}
Utilisez les mêmes méthodes mais assurez-vous de mettre ces implémentations dans initialization, onAttach(), or onCreate()
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)
}
}
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 :
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... } } }
Lancer l'action
val i = Intent(this, TargetActivity::class.java) myActionResult.launch(i)
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.
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.
0 votes
C'est difficile de tester la chose maintenant :(
1 votes
Je peux comprendre pourquoi Google a décidé de suivre cette voie, il essaie de découpler
startActivityForResult
du cycle de vie de la vue. Je souhaitais simplement qu'il y ait un moyen plus élégant de le faire.0 votes
Le site docs ne le montre pas comme étant déprécié.
0 votes
Veuillez consulter cette documentation officielle. J'espère que cela vous aidera. developer.Android.com/training/basics/intents/résultat
0 votes
StartActivityForResult semble également déprécié. Est-ce le cas ?