StartActivityForResult is the Core/OG Component of the Android Activity Ecosystem of how we used to start an activity & get results from it with this getting deprecated we have got a new & better way RegisterActivityForResult.
Why was StartActivityForResult deprecated?
StartActivityForResult is the most fundamental component of the Android ecosystem but with its simple-to-use advantage it had many disadvantages like
- Hard to find from where a certain request is being made
- Had to send a unique request code in case there is a duplicate used. that can lead to buggy results sometimes
- The result is missed if the component is recreated
- onActivityResult callback doesn’t work well with fragments
Why new Activity Result is better?
- Simple, easy & clean
- Inbuilt & Custom Contract-based Support
- Separate callback for each activity (earlier for each we used to have a common activity Result)
How to use Activity Result API
Step 1: Declare the launcher
lateinit var launcher : ActivityResultLauncher
Step 2: Register it
launcher = registerForActivityResult (ActivityResultContracts.StartActivityForResult()) { result -> useTheResult(result) }
Note: You must call registerForActivityResult() before the fragment or activity is created; you cannot launch the
ActivityResultLauncher until the fragment or activity’s
Lifecycle has reached
CREATED.
Step 3: Use the launcher
launcher.launch(Intent(context, ResultActivity::class.java) .putExtra(ResultActivity.PARAM_DATA,id))
Now in this way whenever we can easily & efficiently refactor all the old startActivityForResult()
Some of the Built-in ActivityResultContracts are :
- StartActivityForResult
- RequestPermission
- TakePicture
- CaptureVideo
- OpenDocument
You can find more here: https://developer.android.com/reference/androidx/activity
Along with these inbuilt result type contracts, there is also support for custom contracts i.e
class CustomContract : ActivityResultContract<String, String?>() { | |
const val DATA = "data" | |
const val INPUT_DATA = "input_data" | |
override fun createIntent(context: Context, input: String?): Intent { | |
val intent = Intent(context, DummyResultActivity::class.java) | |
intent.putExtra(INPUT_DATA, input) | |
return intent | |
} | |
override fun parseResult(resultCode: Int, intent: Intent?): String? { | |
return when (resultCode) { | |
//Transforming our result to required format before returning it | |
Activity.RESULT_OK -> intent?.getStringExtra(DATA) | |
else -> null | |
} | |
} | |
} |
Some Additional thoughts?
With Custom Contract we can separate all the logic to the Contract Class
Though this is a much better way as compared to what we have earlier still this is coupled with our activity.
In order to decouple it a bit, we can make use of customization with live data & lifecycle observer.
Further reading
⨭ Getting a result from an activity | Official Documentation
⨭ Introducing the Activity Results APIs | Adam Bennett
Catch me on Twitter: https://twitter.com/its_pra_tick
This article was originally published on proandroiddev.com on September 27, 2022