The following code gives me error as registering occurs after onResume:
class TempActivity: AppCompatActivity(){
private lateinit var binding: ActivityTempBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityTempBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.tempBtn.setOnClickListener {
val a = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
//SomeCode
}
a.launch(
//SomeIntent
)
}
}
However, if I use activityResultRegistry, I am not getting any errors. The code is
class TempActivity: AppCompatActivity(){
private lateinit var binding: ActivityTempBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityTempBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.tempBtn.setOnClickListener {
val a = activityResultRegistry.register("key", ActivityResultContracts.StartActivityForResult()){
// SomeCode
}
a.launch(
//Some Intent
)
}
}
The latter code run without any problem and launches the corresponding intent. I just want to know how safe is latter one and is there any unwanted behaviors I should be aware of?
It gives you an error because you are registering the contract conditionally after the Activity is well into its lifecycle.
The guide says:
It's clear that if you register something after the Activity is created and it only happens when a condition (click event in this case) is met, the order of registration cannot be ensured.
A better solution would be to register the contract before the Activity is created and just call
launch()
when you need it. The guide, once again, says it is completely safe:So in your case, the Activity would look like this:
Further explanation:
The
registerForActivityResult()
is a convenience method that internally calls the registry'sregister
method with an automatically created key. The key is derived from an internalAtomicInteger
that is retrieved and incremented every time you callregisterForActivityResult()
. Since this key is used to look up the callback that will handle the result, every call to theregisterForActivityResult
must be in the same order, otherwise it might happen that you once call it in the order of A (key=0), B (key=1) but then you call it B (key=0), A (key=1), or not even call the register method for one of the contracts (this is exactly what happens when you register in theOnClickListener
).In your specific case if the Activity gets recreated while you're waiting for the launched contract to return (for example, configuration change happens or the system simply kills the app), the callback will be removed from the registry (the key remains there though), meaning that it will not be called with the results.
So, to summarize the whole thing: you can (should) safely register any contract as a member field in your Activity or in the
onCreate(...)
, and you should never register a contract on-the-fly (a.k.a. conditionally). Registering the contract will do nothing special, the real deal happens when you launch it.