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

Kotlin开发:如何从其他类更新RecyclerView的List Adapter

解决Kotlin中跨类更新RecyclerView的问题

我来帮你搞定这个跨类更新RecyclerView的难题~你现在遇到的核心矛盾是:实例方法updateList没法被其他类静态调用,放进伴生对象又拿不到rv_list控件。下面给你几种符合Android开发最佳实践的解决方案,按推荐程度排序:


方案1:用ViewModel + LiveData(最推荐)

这是Jetpack架构组件的标准做法,能完美解耦Activity和其他业务类,还自带生命周期感知,完全避免内存泄漏。

步骤1:创建GroupsViewModel

专门用来管理分组数据的生命周期:

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class GroupsViewModel : ViewModel() {
    // 可变的内部数据,外部只能观察不能修改
    private val _groupList = MutableLiveData<List<GroupModel>>()
    // 对外暴露不可变的LiveData,供UI观察
    val groupList = _groupList

    // 提供更新数据的方法,外部通过这个方法修改数据
    fun updateGroups(newGroups: List<GroupModel>) {
        // postValue适合在非主线程调用,自动切换到主线程更新UI
        _groupList.postValue(newGroups)
    }
}

步骤2:改造GroupsActivity

让Activity观察ViewModel的数据变化,自动更新RecyclerView:

class GroupsActivity : AppCompatActivity() {
    private val TAG = "GroupsActivity"
    private lateinit var viewModel: GroupsViewModel
    private lateinit var listAdapter: GroupsListAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_groups)

        // 初始化ViewModel
        viewModel = ViewModelProvider(this)[GroupsViewModel::class.java]

        // 初始化RecyclerView和适配器
        rv_list.layoutManager = LinearLayoutManager(this)
        rv_list.setHasFixedSize(true)
        listAdapter = GroupsListAdapter(this, emptyList())
        rv_list.adapter = listAdapter

        // 观察数据变化,自动更新UI
        viewModel.groupList.observe(this) { newGroups ->
            listAdapter.updateData(newGroups)
            // 如果你不想修改适配器,也可以重新设置适配器:
            // rv_list.adapter = GroupsListAdapter(this, newGroups)
        }

        if (WebSocketConnection.connected) {
            Log.d(TAG, "WebSocket已连接")
        }
    }
}

步骤3:在异步方法中更新数据

直接调用ViewModel的更新方法就行,不用管Activity的状态:

fun jsonActionCheck(action : String, jsonString: String){
    val gson = Gson()
    when (action){
        "GET_GROUPS" -> {
            val jsonModel : JsonGroups = gson.fromJson(jsonString, JsonGroups::class.java)
            // 获取ViewModel实例(如果是全局WebSocket,用Application级别的ViewModelProvider)
            val appContext = ApplicationProvider.getApplicationContext<Application>()
            val viewModel = ViewModelProvider(appContext as ViewModelStoreOwner)[GroupsViewModel::class.java]
            viewModel.updateGroups(jsonModel.data)
        }
        // 其他action处理...
    }
}

方案2:接口回调+弱引用

如果不想用Jetpack组件,可以用经典的接口回调模式,配合弱引用避免内存泄漏。

步骤1:定义回调接口

interface GroupUpdateCallback {
    fun onGroupsUpdated(newGroups: List<GroupModel>)
}

步骤2:改造GroupsActivity实现接口

class GroupsActivity : AppCompatActivity(), GroupUpdateCallback {
    private val TAG = "GroupsActivity"
    private lateinit var listAdapter: GroupsListAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_groups)

        rv_list.layoutManager = LinearLayoutManager(this)
        rv_list.setHasFixedSize(true)
        listAdapter = GroupsListAdapter(this, emptyList())
        rv_list.adapter = listAdapter

        // 将当前Activity的弱引用传给WebSocket类
        WebSocketConnection.setUpdateCallback(WeakReference(this))
    }

    override fun onGroupsUpdated(newGroups: List<GroupModel>) {
        // 主线程更新列表
        runOnUiThread {
            listAdapter.updateData(newGroups)
        }
    }
}

步骤3:在WebSocket类中持有回调并触发

class WebSocketConnection {
    companion object {
        private var updateCallback: WeakReference<GroupUpdateCallback>? = null

        fun setUpdateCallback(callback: WeakReference<GroupUpdateCallback>) {
            updateCallback = callback
        }

        fun jsonActionCheck(action : String, jsonString: String){
            val gson = Gson()
            when (action){
                "GET_GROUPS" -> {
                    val jsonModel : JsonGroups = gson.fromJson(jsonString, JsonGroups::class.java)
                    // 弱引用获取回调实例,避免内存泄漏
                    updateCallback?.get()?.onGroupsUpdated(jsonModel.data)
                }
                // 其他action处理...
            }
        }
    }
}

方案3:伴生对象+弱引用持有Activity实例

这是对你现有代码改动最小的方案,但要注意内存泄漏问题:

class GroupsActivity : AppCompatActivity() {
    private val TAG = "GroupsActivity"
    private lateinit var listAdapter: GroupsListAdapter

    companion object {
        var active: Boolean = false
        var tableModel: List<GroupModel>? = null
        // 用弱引用持有Activity实例
        private var activityInstance: WeakReference<GroupsActivity>? = null

        fun updateList() {
            activityInstance?.get()?.run {
                // 确保在主线程更新UI
                runOnUiThread {
                    listAdapter.updateData(tableModel ?: emptyList())
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_groups)
        // 初始化弱引用
        activityInstance = WeakReference(this)

        rv_list.layoutManager = LinearLayoutManager(this)
        rv_list.setHasFixedSize(true)
        listAdapter = GroupsListAdapter(this, tableModel ?: emptyList())
        rv_list.adapter = listAdapter

        if (WebSocketConnection.connected) {
            Log.d(TAG, "WebSocket已连接")
        }
    }

    override fun onResume() {
        super.onResume()
        active = true
    }

    override fun onPause() {
        super.onPause()
        active = false
    }

    override fun onDestroy() {
        super.onDestroy()
        // 销毁时清空弱引用
        activityInstance?.clear()
    }
}

现在你在jsonActionCheck里就能直接调用GroupsActivity.updateList()了,而且不会因为持有Activity实例导致内存泄漏。


内容的提问来源于stack exchange,提问作者D.Prieto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:00:40