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 ?
En Java 8, on peut l'écrire comme ceci :
ActivityResultLauncher<Intent> startActivityForResult = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == AppCompatActivity.RESULT_OK) {
Intent data = result.getData();
// ...
}
}
);
Intent intent = new Intent( ... );
startActivityForResult.launch(intent);
onActivityResult
, startActivityForResult
, requestPermissions
y onRequestPermissionsResult
son déprécié en androidx.fragment
de 1.3.0-alpha04
et non sur android.app.Activity
.
Au lieu de cela, vous pouvez utiliser Activity Result APIs
con registerForActivityResult
.
Référence : Kotlin - Choisir une image dans une galerie
L'alternative la plus simple que j'ai trouvée jusqu'à présent.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.id.activity_main)
var ivPhoto = findViewById<ImageView>(R.id.ivPhoto)
var btnChoosePhoto = findViewById<Button>(R.id.btnChoosePhoto)
val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
ivPhoto.setImageURI(uri) // Handle the returned Uri
}
btnChoose.setOnClickListener {
getContent.launch("image/*")
}
}
Mon objectif était de réutiliser l'implémentation actuelle de la fonction startActivityForResult
avec un minimum de modifications du code. Pour cela, j'ai créé une classe et une interface wrapper avec une méthode onActivityResultFromLauncher.
interface ActivityResultLauncherWrapper {
fun launchIntentForResult(activity: FragmentActivity, intent: Intent, requestCode: Int, callBack: OnActivityResultListener)
fun unregister()
interface OnActivityResultListener {
fun onActivityResultFromLauncher(requestCode: Int, resultCode: Int, data: Intent?)
}
}
class ActivityResultLauncherWrapperImpl : ActivityResultLauncherWrapper {
private var weakLauncher: WeakReference<ActivityResultLauncher<Intent>>? = null
override fun launchIntentForResult(
activity: FragmentActivity,
intent: Intent,
requestCode: Int,
callBack: ActivityResultLauncherWrapper.OnActivityResultListener
) {
weakLauncher = WeakReference(
activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
callBack.onActivityResultFromLauncher(requestCode, result.resultCode, result.data)
}
)
weakLauncher?.get()?.launch(intent)
}
override fun unregister() {
weakLauncher?.get()?.unregister()
}
}
J'utilise Dagger dans mon projet et j'ai injecté le wrapper là où il est nécessaire.
@Inject
lateinit var activityResultLauncher: ActivityResultLauncherWrapper
Mais le wrapper peut aussi être instancié directement :
val activityResultLauncher = ActivityResultLauncherWrapper()
alors vous devez changer le startActivityForResult
méthode avec launchIntentForResult
. Voici un exemple où il est appelé à partir d'un fragment :
activityResultLauncher.launchIntentForResult(
requireActivity(),
intent,
REQUEST_CODE_CONSTANT,
object: ActivityResultLauncherWrapper.OnActivityResultListener {
override fun onActivityResultFromLauncher(requestCode: Int, resultCode: Int, data: Intent?) {
/*do something*/
}
}
)
Vous recevrez le résultat dans l'objet anonyme. Vous pouvez utiliser OnActivityResultListener
dans un Fragment ou une ActivitéFragment si vous implémentez l'interface et remaniez l'implémentation actuelle comme ceci :
class MyFragment : Fragment(), OnActivityResultListener {
...
override fun onActivityResultFromLauncher(requestCode: Int, resultCode: Int, data: Intent?) {/*do somthing*/}
...
}
Comme nous le savons, la classe Kotlin ActivityResultLauncherWrapper peut également être utilisée dans le code Java. Il y a aussi des classes java dans mon projet. Il y a un exemple avec l'implémentation de l'interface callback dans un Fragment :
public class MyFragment extends Fragment implements OnActivityResultListener {
...
@Inject
ActivityResultLauncherWrapper activityResultLauncher;
//ActivityResultLauncherWrapper activityResultLauncher = new ActivityResultLauncherWrapper()
...
public void launnchActivity(@NotNull Intent intent) {
activityResultLauncher.launchIntentForResult(requireActivity(), intent, REQUEST_CODE_CONSTANT, this);
}
...
@Override
public void onActivityResultFromLauncher(int requestCode, int resultCode, Intent data) {/*do somthing*/}
...
}
J'espère que cela vous aidera à trouver la solution à votre cas.
Vous pouvez utiliser des fonctions d'extension pour Koltin. Par exemple :
//random utils file
fun Fragment.buildGetContentRequest(function: (Uri) -> Unit): ActivityResultLauncher<String> {
return this.registerForActivityResult(ActivityResultContracts.GetContent()) {
function(it)
}
}
fun Fragment.buildTakePhotoRequest(function: (Boolean) -> Unit): ActivityResultLauncher<Uri> {
return this.registerForActivityResult(ActivityResultContracts.TakePicture()) {
function(it)
}
}
fun Fragment.buildSelectMultipleContentRequest(function: (MutableList<Uri>?) -> Unit): ActivityResultLauncher<String> {
return this.registerForActivityResult(ActivityResultContracts.GetMultipleContents()) {
function(it)
}
}
Et ensuite, dans votre fragment, quelque chose comme ceci
//your actual fragment logic
class YourFragment : Fragment() {
//we can assign our request in init process
private val mRequestSelectFiles = buildSelectMultipleContentRequest {
onFilesSelected(it)
}
fun onSelectFiles() {
val mime = "*/*"
mRequestSelectFiles.launch(mime)
}
fun onFilesSelected(list: MutableList<Uri>?) {
//your logic
}
}
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 ?