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

如何在伴生对象中定义带OnClickListener的Adapter并解决this报错?

你现在的问题核心有两个:

  • 伴生对象里的this指的是Companion静态内部类的实例,不是MainActivity的实例,而Adapter大概率需要Context或者Activity上下文,所以传这个this肯定报错。
  • 用伴生对象存列表、Adapter这种和UI绑定的对象,很容易造成内存泄漏——因为静态变量的生命周期和App一致,MainActivity销毁后,这些变量还持有Activity相关引用,内存没法释放。
正确实现方式

方式1:用Activity Result API回传数据(最常用)

从其他Activity收集完数据后,通过Intent把数据带回来,MainActivity接收后更新RecyclerView:

  1. 首先在MainActivity里注册Activity Result回调:
// MainActivity.kt
class MainActivity : AppCompatActivity() {
    private lateinit var recyclerView: RecyclerView
    private lateinit var adapter: Adapter
    private val recyclerViewItems = ArrayList<Itemclass>()

    // 注册回调,接收其他Activity返回的数据
    private val getInputData = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == RESULT_OK) {
            val data = result.data ?: return@registerForActivityResult
            // 取出返回的名称和列表
            val name = data.getStringExtra("KEY_NAME") ?: ""
            val questionList = data.getSerializableExtra("KEY_QUESTION_LIST") as? ArrayList<QuestionItemClass> ?: arrayListOf()
            
            // 封装成Item并添加到列表,更新Adapter
            val newItem = Itemclass(name, questionList)
            recyclerViewItems.add(newItem)
            adapter.notifyItemInserted(recyclerViewItems.size - 1)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 初始化RecyclerView和Adapter
        recyclerView = findViewById(R.id.recyclerView)
        adapter = Adapter(recyclerViewItems, this) // 这里的this是MainActivity实例,没问题
        recyclerView.adapter = adapter
        recyclerView.layoutManager = LinearLayoutManager(this)

        // 跳转到其他Activity的按钮点击事件
        findViewById<Button>(R.id.btn_go_other).setOnClickListener {
            val intent = Intent(this, OtherActivity::class.java)
            getInputData.launch(intent)
        }
    }
}
  1. 在其他Activity里,收集完数据后通过Intent返回:
// OtherActivity.kt
class OtherActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_other)

        // 假设收集完数据后,点击确认按钮返回
        findViewById<Button>(R.id.btn_confirm).setOnClickListener {
            val inputName = "用户输入的名称" // 替换成实际获取的名称
            val inputList = arrayListOf<QuestionItemClass>() // 替换成实际获取的列表
            
            val resultIntent = Intent()
            resultIntent.putExtra("KEY_NAME", inputName)
            // 注意:QuestionItemClass需要实现Serializable或者Parcelable接口
            resultIntent.putExtra("KEY_QUESTION_LIST", inputList)
            setResult(RESULT_OK, resultIntent)
            finish()
        }
    }
}

注意:QuestionItemClass需要实现Serializable或者Parcelable接口,这样才能通过Intent传递。

方式2:用ViewModel共享数据(适合复杂场景)

如果你的页面逻辑比较复杂,或者需要在多个组件间共享数据,可以用ViewModel:

  1. 创建共享的ViewModel:
// SharedViewModel.kt
class SharedViewModel : ViewModel() {
    val itemList = MutableLiveData<ArrayList<Itemclass>>()

    init {
        itemList.value = arrayListOf()
    }

    fun addItem(name: String, list: ArrayList<QuestionItemClass>) {
        val currentList = itemList.value ?: arrayListOf()
        currentList.add(Itemclass(name, list))
        itemList.postValue(currentList)
    }
}
  1. MainActivity里观察ViewModel的数据变化:
// MainActivity.kt
class MainActivity : AppCompatActivity() {
    private lateinit var recyclerView: RecyclerView
    private lateinit var adapter: Adapter
    private lateinit var viewModel: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 获取ViewModel实例
        viewModel = ViewModelProvider(this)[SharedViewModel::class.java]
        
        // 初始化RecyclerView
        recyclerView = findViewById(R.id.recyclerView)
        adapter = Adapter(arrayListOf(), this)
        recyclerView.adapter = adapter
        recyclerView.layoutManager = LinearLayoutManager(this)

        // 观察列表变化,自动更新RecyclerView
        viewModel.itemList.observe(this) { newList ->
            adapter.updateList(newList)
            adapter.notifyDataSetChanged()
        }

        // 跳转到其他Activity
        findViewById<Button>(R.id.btn_go_other).setOnClickListener {
            val intent = Intent(this, OtherActivity::class.java)
            startActivity(intent)
        }
    }
}
  1. 其他Activity里获取ViewModel并添加数据:
// OtherActivity.kt
class OtherActivity : AppCompatActivity() {
    private lateinit var viewModel: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_other)
        
        // 获取和MainActivity共享的ViewModel
        viewModel = ViewModelProvider(this@OtherActivity)[SharedViewModel::class.java]

        findViewById<Button>(R.id.btn_confirm).setOnClickListener {
            val inputName = "用户输入的名称"
            val inputList = arrayListOf<QuestionItemClass>()
            
            viewModel.addItem(inputName, inputList)
            finish()
        }
    }
}

为什么原来的伴生对象方案不行?

  • 伴生对象是静态成员,它的this指向的是MainActivity.Companion这个静态类实例,不是MainActivity的上下文,所以Adapter接收的Context是错的,导致报错。
  • 静态变量持有Adapter、列表这些对象,会让MainActivity即使销毁后也无法被GC回收,造成内存泄漏,严重影响App性能。

内容的提问来源于stack exchange,提问作者Mehmet Eren Erol

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 11:08:01