Looking For Anything Specific?

[Tutorial] Android Activity Result API with Custom Contract and Parcelable Example Code

 Hi There,

Well, In a recent article we have shared a bit about the new Android activity result API, since the startActivityForResult and onActivityResult are deprecated, we have some new API's to work with to achieve the same functionality, the idea is simple we start a new activity and do some operation and get the result back from the activity, for this we used the famous startActivityForResult and onActivityResult, but both are deprecated in the updated Activity class so we continued to explore and found the Activity Result API which is a better replacement compared to the previous implementation as it verifies type-safe and reduce the boilerplate code and improves the implementation to look more readable.

android activity result api custom contract sample code


How to get android activity result using ActivityResult API:

We discussed in an earlier article, so a quick recap, we register the callback registerForActivityResult for which we will provide an ActivityResultContract and ActivityResultCallback which we will give us an ActivityResultLauncher and we simply launch from there to start a new activity and the result will be handled in the ActivityResultCallback. In our previous example, we used one of the provided  ActivityResultContract which is the StartActivityForResult contract to start and get the result back since its a generic one it doesn't support type-safe, so now we are going for a custom contract which will make our code a little bit clean and verify type-safe. 

Check out the previous article: How to use activity result API

ActivityResult API Custom Contract:

So we learned that to register for activity result we need to provide it with an ActivityResultContract, according to the documentation 
A contract specifying that an activity can be called with an input of type I and produce an output of type O

Well that put things in perspective, right?  Generally, we start an activity with an input that we want to pass on to the next activity and we will get back the result as an output with this it will make sure the input and output are type-safe and a contract will be a new class which makes the code less complex, Let's start with creating a custom contract class and we name it CustomContractParcelable. Why parcel able because that way only we can pass on data class in kotlin you can read Parcelable About Here

CustomContractParcelable.kt


  class CustomContractParcelable<T : Parcelable?> : ActivityResultContract<Intent,T>(){
    override fun createIntent(context: Context, inputAsIntent: Intent?): Intent {
        return inputAsIntent!!
    }

    override fun parseResult(resultCode: Int, intent: Intent?): T? {
        return if (resultCode == Activity.RESULT_OK){
            return intent?.getParcelableExtra<T>(PARCELABLE_RESULT)
        }else{
            null
        }
    }

}
  

Above is the sample code for a custom contract for ActivityResultContract, First, we extend the ActivityResultContract which requires two type parameters an Input and Output.

This class must override the above two methods which are createIntent(context: Context, inputAsIntent: Intent)  in here the second parameter is actually the input type parameter we mentioned in ActivityResultContract the input type could be anything so to make our contract more accessible and make it able to start more than one activity we are providing the intent itself as an input, the second method that overrides is parseResult(resultCode: Int, intent: Intent?) once the started activity finishes this method will be called and it will return the data of type we mentioned in the output parameter which makes this implementation type-safe and we can check the result code as well in here to pass the result back to our call back.

Use Custom Contract With ActivityResult API to get result:

After creating our custom contract for the Activity Result API we can use that to start our activity this is the same as we shared in the previous article, instead of providing the StartActivityForResult contract we will pass our own Custom contract to registerForActivityResult see the sample implementation below

  private val secondActivityWithResult =
        registerForActivityResult(CustomContractParcelable<SampleModel>()) { result ->
            if (result != null) {
                resultTextView.text = result.description
            }
        }
  
To make sure the type of data we want we have to mention the parcelable type a SampleModel is a simple data class with extends a parcelable so that our callback will give the same result. And in a click action or where ever you want to start the activity call launch. 

 
  getResultButton.setOnClickListener {
            secondActivityWithResult.launch(Intent(requireContext(), SecondActivity::class.java))
        }
  
Since our input parameter is an intent, In our launch we have to pass the intent for which we want to start the activity. 


So why this way you may ask, the reason is that we can pass more than one parameter in our intent when starting a new activity, and this way this class stays generic to make it accessible to start more than one activity since we are passing the intent as a parameter, and while receiving a result if we want to receive a bunch of data we can simply create a data class and pass the data through it.

Setting the result on the second activity is the same as before, we simply call setResult with the intent as the result.

How to Use ActivityResult API in a fragment:

To be honest, there is nothing more to do to make this implementation in a fragment, if you see in our above code that we used requireContent() function when creating the intent because we used this example from the fragment. You can get the complete project code to understand more in detail about the implementation in the fragment. 



Note: This project mentioned in the same GitHub repo as the previous post example but under a different branch namely custom-contract.  As a bonus, I have also included a custom contract to work with strings you can check that out in the repo.

Thanks for reading, Sharing is Caring!!! 
Don't forget to Like Our Facebook Page.

keywords:
activity result api custom contract kotlin
how to use activityresult api with a custom contract in android with kotlin


Post a Comment

0 Comments