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.

14voto

syslogic Points 749

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);

4 votes

Comment puis-je gérer le code de demande multiple ? Veuillez m'aider. Merci d'avance.

1 votes

Un Intent n'a évidemment qu'un seul code de demande.

7voto

Aigori Points 82

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 .

0 votes

Où avez-vous appris l'existence de cette "Activity Result APIs" avec "registerForActivityResult", quelle en est la source ?

0 votes

@Sumit Comme j'ai lié le journal de changement sur le texte déprécié L'équipe Android a répondu : "Veuillez utiliser les API de résultats d'activité".

5voto

Allan_Aj5 Points 27

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

    }

3voto

MeLine Points 399

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.

3voto

Dwane13 Points 25

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

0 votes

Vous devez ajouter les dépendances suivantes : - implémentation "androidx.activity:activity-ktx:1.3.0" implémentation "androidx.fragment:fragment-ktx:1.3.6".

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