如何在ViewModel中访问assets目录下JSON文件以加载RecyclerView?
解决ViewModel读取Assets中JSON数据的问题
核心问题
ViewModel不能直接持有Context(会导致内存泄漏,且ViewModelProvider默认要求空构造),直接传Context的方式本身就不符合ViewModel的设计规范,这也是你添加空构造后仍无法获取数据的原因——空构造下ViewModel拿不到AssetManager来读取JSON。
正确实现步骤
- 创建ViewModel工厂类,用来向ViewModel传递AssetManager(而非直接传Context)
- 在ViewModel中通过AssetManager读取JSON,并通过LiveData通知UI更新
- 在Activity中通过工厂类获取ViewModel,观察LiveData更新RecyclerView
代码示例
1. ViewModel工厂类
class MyViewModelFactory(private val assetManager: AssetManager) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { if (modelClass.isAssignableFrom(MyViewModel::class.java)) { @Suppress("UNCHECKED_CAST") return MyViewModel(assetManager) as T } throw IllegalArgumentException("Unknown ViewModel class") } }
2. ViewModel实现
class MyViewModel(private val assetManager: AssetManager) : ViewModel() { // 用LiveData持有数据,确保数据变化能通知UI private val _dataList = MutableLiveData<List<YourDataModel>>() val dataList: LiveData<List<YourDataModel>> get() = _dataList init { // 初始化时加载JSON数据 loadJsonFromAssets() } private fun loadJsonFromAssets() { try { // 读取assets下的JSON文件 assetManager.open("your_data.json").use { inputStream -> val jsonString = inputStream.bufferedReader().readText() // 解析JSON为数据模型列表(这里以Gson为例,你也可以用Moshi/Jackson) val dataArray = Gson().fromJson(jsonString, Array<YourDataModel>::class.java) _dataList.postValue(dataArray.toList()) } } catch (e: IOException) { e.printStackTrace() // 处理文件读取失败的情况,比如给_dataList.postValue空列表或错误提示 } } }
3. Activity中初始化ViewModel并观察数据
class YourActivity : AppCompatActivity() { private lateinit var viewModel: MyViewModel private lateinit var adapter: YourRecyclerViewAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_your) // 初始化Adapter adapter = YourRecyclerViewAdapter() findViewById<RecyclerView>(R.id.recycler_view).apply { this.adapter = adapter layoutManager = LinearLayoutManager(this@YourActivity) } // 通过工厂类获取ViewModel val factory = MyViewModelFactory(assets) viewModel = ViewModelProvider(this, factory)[MyViewModel::class.java] // 观察LiveData,更新RecyclerView viewModel.dataList.observe(this) { dataList -> adapter.submitList(dataList) // 如果用ListAdapter,用submitList;普通Adapter则直接set数据并notify } } }
排查要点
- 确认JSON文件名正确(assets目录下直接写文件名,不要加
assets/前缀) - 检查数据模型类的字段和JSON键名对应(大小写、名称一致,或用
@SerializedName注解) - 确保LiveData的
observe方法正确绑定了Activity的生命周期,数据加载完成后能触发UI更新
内容的提问来源于stack exchange,提问作者Dragamaroon
相关产品推荐
相关产品推荐

