简体   繁体   中英

registerForActivityResult not working when second activity orientation changes

I am calling activity B from activity A using the ActivityResultLauncher and setting the result from activity B when the task is done. This works perfectly if orientation is not changed. The problem is when I change orientation from activity B and then setting the result, then registerForActivityResult of activity A is not called. Could someone let me know, what could be the issue?

Note: I do not face this issue if I am using startActivityForResult and onActivityResult . I changed this to ActivityResultLauncher as startActivityForResult became deprecated .

activity A sample code:

private lateinit var launcher: ActivityResultLauncher<Intent>

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(layout)
    setLauncherResult()
}

private fun setLauncherResult() {
    launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
        if (result.resultCode == Activity.RESULT_OK) {
            //Do operations here
        }
}

 //On button click starting activity B using launcher
 val intent = Intent(activityA, activityB)
 launcher.launch(intent)

}

activity B sample code:

//setting result
val intent = Intent()
//set intent extras
setResult(Activity.RESULT_OK, intent)
finish()

You can save the value in onSaveInstanceState() and use setResult in onRestoreInstanceState() .

Try moving the registerForActivityResult assignment of launcher to onCreateView() (override it if you haven't already). Putting it here, I'm not getting the "is attempting to register while current state is STARTED" RuntimeException in OnCreateView() as it would with onResume() or later. The advantage of OnCreateView() over OnCreate() seems to be that the launcher variable will get re-set on theme day/night changes as well as just orientation changes.

Also see the Configuration change & Process death section here for more discussion.

I know the official dox say it's safe to set it before anything else in the class, but theme changes broke .launch() , and this location appears to work for me.

Everytime orientation changes it calls onCreate and it resets your views & Other variables like launcher are re-assigned. So you can follow the example shown in official document here: https://developer.android.com/training/basics/intents/result#launch

And pull your launcher assignment out of onCreate as following (This worked for me):

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding


    private val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
        if (result.resultCode == Activity.RESULT_OK) {
            //do your stuff here
            binding.tv.text = result.data?.getStringExtra("text")
        }
    }


    companion object {
        var number : Int = 0
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.tv.setOnClickListener {
            val intent = Intent(this, ActivityB::class.java)
            startForResult.launch(intent)
        }
    }
}

If you don't want that onCreate should be called again when orientation changes. Then in your Manifest you can add configChanges :

<activity android:name=".MainActivity"
            android:configChanges="orientation|screenSize">

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM