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

如何向AndroidViewModel传参以过滤assets目录下的JSON文件?

最优实现方案

你的场景最优解法是自定义ViewModelFactory,同时传入Application实例和分类过滤参数,既满足访问assets需要上下文的要求,又能把过滤参数传递到ViewModel内部,无需创建多个ViewModel实例,完全符合Android官方架构规范。


步骤1:修改ViewModel构造函数,增加过滤参数

调整原有ViewModel的构造,新增分类过滤参数作为构造入参,同时优化原有冗余逻辑:

class GuideViewModel(
    application: Application,
    // 新增分类过滤参数
    private val filterCategory: String
) : AndroidViewModel(application) {
    private val _name = MutableLiveData<String>()
    val name: LiveData<String> get() = _name

    private val _difficulty = MutableLiveData(3)
    val difficulty: LiveData<Int> get() = _difficulty

    private val _date = MutableLiveData<Long>(3010)
    val date: LiveData<Long> get() = _date

    private val _graphic = MutableLiveData<String>()
    val graphic: LiveData<String> get() = _graphic

    // 初始化时直接加载并过滤数据,无需外部调用触发
    init {
        loadJsonData()
    }

    private fun loadJsonData() {
        try {
            val jsonString = loadJsonDataFromFile()
            val json = JSONObject(jsonString)
            val jsonBrewers = json.getJSONArray("movies")

            for (index in 0 until jsonBrewers.length()) {
                val item = jsonBrewers.getJSONObject(index)
                // 用构造传入的过滤参数做匹配
                if (item.getString(KEY_NAME) == filterCategory) {
                    _name.value = item.getString(KEY_NAME)
                    _difficulty.value = item.getInt(KEY_DIFFICULTY)
                    _date.value = item.getLong(KEY_DATE)
                    _graphic.value = item.getString(KEY_GRAPHIC)
                    // 匹配到目标就跳出循环,减少无效遍历
                    break
                }
            }
        } catch (e: JSONException) {
            e.printStackTrace()
        }
    }

    private fun loadJsonDataFromFile(): String {
        var json = ""
        try {
            val input = getApplication<Application>().assets.open("movies.json")
            val size = input.available()
            val buffer = ByteArray(size)
            input.read(buffer)
            input.close()
            json = buffer.toString(Charsets.UTF_8)
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return json
    }

    companion object {
        private const val KEY_NAME = "name"
        private const val KEY_DIFFICULTY = "difficulty"
        private const val KEY_DATE = "date"
        private const val KEY_GRAPHIC = "graphic"
    }
}

步骤2:实现自定义ViewModelFactory

因为原生ViewModelFactory不支持带自定义参数的AndroidViewModel创建,需要自己实现Factory:

class GuideViewModelFactory(
    private val application: Application,
    private val filterCategory: String
) : ViewModelProvider.Factory {
    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(GuideViewModel::class.java)) {
            return GuideViewModel(application, filterCategory) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

步骤3:在Activity/Fragment中实例化ViewModel

传入需要的分类参数,创建ViewModel实例后直接观察LiveData即可:

Activity中使用示例

class GuideActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 替换为你实际需要的分类参数
        val targetCategory = "你需要的分类值"
        val viewModelFactory = GuideViewModelFactory(application, targetCategory)
        val viewModel = ViewModelProvider(this, viewModelFactory)[GuideViewModel::class.java]

        // 观察数据更新UI
        viewModel.name.observe(this) { name ->
            // 更新名称UI
        }
        viewModel.difficulty.observe(this) { difficulty ->
            // 更新难度UI
        }
    }
}

Fragment中使用示例

class GuideFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 替换为你实际需要的分类参数
        val targetCategory = "你需要的分类值"
        val viewModelFactory = GuideViewModelFactory(requireActivity().application, targetCategory)
        val viewModel = ViewModelProvider(this, viewModelFactory)[GuideViewModel::class.java]

        // 观察数据更新UI即可
    }
}

额外优化建议

  • 如果需要频繁切换分类过滤,不需要重建ViewModel,可在ViewModel内新增setFilterCategory()方法,传入新参数后重新执行过滤逻辑即可
  • assets的JSON文件如果是固定内容,可添加缓存逻辑,不需要每次过滤都重新读取本地文件,提升运行性能
  • 生产环境建议用Gson/Moshi等JSON解析库替代原生JSONObject,减少手写解析的出错概率

内容的提问来源于stack exchange,提问作者byrnec25

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 08:39:02