androidstart-activityregisterforactivityresult

Android app exits when launch another activity using registerForActivityResult


I have 2 classes MainActivity and EditActivity. I try to launch EditActivity with registerForActivityResult() in MainActivity but the app exits immediately; startActivity() works fine but registerForActivityResult() serves my purpose, which is returning result to MainActivity. The function that launches EditActivity is as below.

MainActivity.kt

fun launchEditView(position: Int) {
        val getResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            if(it.resultCode == Activity.RESULT_OK){
                val value = it.data?.getStringExtra("alternative")
                listOfTasks.set(position, value.toString())
                adapter.notifyDataSetChanged()
                saveItems()
            }
        }
        // first parameter is the context, second is the class of the activity to launch
        val intent = Intent(this, EditActivity::class.java)
        intent.putExtra("taskName", listOfTasks.get(position))

        getResult.launch(intent)
    }

Update: the error is

java.lang.IllegalStateException: LifecycleOwner com.example.simpletodo.MainActivity@3a90598 is attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.
        at androidx.activity.result.ActivityResultRegistry.register(ActivityResultRegistry.java:123)
        at androidx.activity.ComponentActivity.registerForActivityResult(ComponentActivity.java:682)
        at androidx.activity.ComponentActivity.registerForActivityResult(ComponentActivity.java:691)
        at com.example.simpletodo.MainActivity.launchEditView(MainActivity.kt:86)

Solution

  • The problem as you see the logcat is that you are trying to register in a wrong state. You have to do it before that activity state comea to resumed state. So, to solve this issue you have to register in your onCreate method of your activity and hold the launcher instance. Then anytime you want to start another activity you can use it. As a sample code:

    lateinit var launcher: ActivityResultLauncher
    
    override fun onCreate(savedInstanceState: Bundle?) {
        //The common logic of onCreate method
        val launcher= registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
                if(it.resultCode == Activity.RESULT_OK){
                    val value = it.data?.getStringExtra("alternative")
                    listOfTasks.set(position, value.toString())
                    adapter.notifyDataSetChanged()
                    saveItems()
                }
            }
    }
    
    fun launchEditView(position: Int) {
            val intent = Intent(this, EditActivity::class.java)
            intent.putExtra("taskName", listOfTasks.get(position))
            launcher.launch(intent)
        }