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
相关产品推荐
相关产品推荐

