You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin实现Activity间数据回传并返回MainActivity更新列表

问题原因
  • 现有代码的核心错误是返回数据时重新创建了MainActivity实例跳转,而非将数据回传给已存在的原MainActivity,会直接导致回退栈混乱、原有页面状态丢失,加上你直接传递EditText的Editable类型数据、没有做类型转换,很容易触发崩溃。
  • 你在MainActivity中预先定义的两个变量enteredPlayerNumber、enteredPlayerName根本不会被赋值,因为你跳转的是全新的MainActivity,和原来打开AddPlayerActivity的实例不是同一个对象。
  • 额外问题:直接在onCreate中调用ViewModel()构造实例是错误用法,配置变更(比如屏幕旋转)时数据会丢失,必须通过系统提供的ViewModelProvider获取实例。
实现步骤

使用官方推荐的Activity Result API实现数据回传,不需要提前定义变量等待数据,只有当AddPlayerActivity关闭返回时才会触发回调读取数据,完全避免提前读取的问题。

1. 修改MainActivity代码

class MainActivity : AppCompatActivity() {
    // 定义传值Key,避免硬编码写错
    companion object {
        const val EXTRA_PLAYER_NAME = "USERNAME"
        const val EXTRA_PLAYER_NUMBER = "USER_NUMBER"
    }

    // 注册页面返回结果回调
    private val addPlayerLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == RESULT_OK) {
            val data = result.data ?: return@registerForActivityResult
            // 从返回的Intent中取值,做类型转换
            val playerName = data.getStringExtra(EXTRA_PLAYER_NAME) ?: return@registerForActivityResult
            val playerNumber = data.getIntExtra(EXTRA_PLAYER_NUMBER, 0)
            // 将数据添加到ViewModel的列表中
            (myViewModel.myList.value as? MutableList)?.add(Player(playerNumber, playerName))
            // 触发LiveData观察者刷新列表,如果使用StateFlow等其他可观察类型对应调整即可
            myViewModel.myList.value = myViewModel.myList.value
        }
    }

    private lateinit var myViewModel: MyViewModel
    private lateinit var myRecyclerView: RecyclerView
    private lateinit var btnAdd: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        myRecyclerView = findViewById(R.id.recyclerView)
        // 正确获取ViewModel实例,不要直接构造
        myViewModel = ViewModelProvider(this)[MyViewModel::class.java]
        btnAdd = findViewById(R.id.btnAdd)

        myRecyclerView.layoutManager = LinearLayoutManager(this)
        myViewModel.getUserData()

        btnAdd.setOnClickListener {
            val myIntent = Intent(this, AddPlayerActivity::class.java)
            // 用注册好的launcher打开AddPlayerActivity,不要直接调用startActivity
            addPlayerLauncher.launch(myIntent)
        }

        myViewModel.myList.observe(this) {
            myRecyclerView.adapter = MyAdapter(it)
        }
    }
}

注意:上述代码中的Player是你的玩家数据实体类,替换成你项目中实际定义的类即可。

2. 修改AddPlayerActivity代码

class AddPlayerActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_add_player)

        val numberAddPlayer = findViewById<EditText>(R.id.etNumberAdd2)
        val nameAddPlayer = findViewById<EditText>(R.id.etNameAdd2)
        val btn = findViewById<Button>(R.id.btnSubmitAdd2)

        btn.setOnClickListener {
            // 基础输入校验,避免空内容或格式错误提交
            val inputName = nameAddPlayer.text.toString().trim()
            val inputNumberStr = numberAddPlayer.text.toString().trim()
            if (inputName.isEmpty() || inputNumberStr.isEmpty()) {
                Toast.makeText(this, "请输入完整的玩家信息", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }
            val inputNumber = inputNumberStr.toIntOrNull() ?: run {
                Toast.makeText(this, "号码必须为数字", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }

            // 构造返回用Intent,不要重新创建MainActivity的Intent
            val resultIntent = Intent()
            resultIntent.putExtra(MainActivity.EXTRA_PLAYER_NAME, inputName)
            resultIntent.putExtra(MainActivity.EXTRA_PLAYER_NUMBER, inputNumber)
            // 设置返回结果码
            setResult(RESULT_OK, resultIntent)
            // 关闭当前页面,自动回到原有MainActivity实例
            finish()
        }
    }
}
关键注意点
  • 页面间回传数据绝对不要在返回时重新启动上一个页面,会导致回退栈堆积、状态丢失,正确逻辑是关闭当前页面,通过系统提供的结果回调把数据传回已经存在的上一个页面实例。
  • 从EditText获取输入内容时,必须调用toString()转成字符串,不能直接传递text属性(它是Editable类型,跨Activity传递时容易触发类型转换异常)。
  • 数字类型输入要做格式校验,避免用户输入非数字内容时调用toInt()触发崩溃。
  • 只有当AddPlayerActivity执行完提交、关闭页面后,MainActivity的结果回调才会执行,完全不会出现提前读取变量的问题。

内容的提问来源于stack exchange,提问作者M.hossein Karimi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:48:22