如何将资源传递给 ViewModel

How can I pass Resources to ViewModel

这种情况需要将Resources传递给ViewModelproperties,所以必须将Resources作为argument传递] 到 constructor.

ViewModel

class WorkoutListViewModel(private val resources: Resources) : ViewModel(){
    private var _part :MutableLiveData<String> = MutableLiveData()
    private var _list : MutableLiveData<List<String>> = MutableLiveData(arrayListOf())
    private val workoutListSource : WorkoutListSource by lazy { WorkoutListLocalSource(resources) }

    val list = _list
    val part = _part

    fun setList(part : String) {
        _part.value = part
        when(_part.value) {
            "CHEST" -> _list.value = workoutListSource.getWorkoutListByPart(BodyType.CHEST)
            "BACK" -> _list.value = workoutListSource.getWorkoutListByPart(BodyType.BACK)
            "LEG" -> _list.value = workoutListSource.getWorkoutListByPart(BodyType.LEG)
            "SHOULDER" -> _list.value = workoutListSource.getWorkoutListByPart(BodyType.SHOULDER)
            "BICEPS" -> _list.value = workoutListSource.getWorkoutListByPart(BodyType.BICEPS)
            "TRICEPS" -> _list.value = workoutListSource.getWorkoutListByPart(BodyType.TRICEPS)
            "ABS" -> _list.value = workoutListSource.getWorkoutListByPart(BodyType.ABS)
        }
    }
}

界面

interface WorkoutListSource {
    fun getWorkoutListByPart(type: BodyType) : List<String>
}

接口的实现

class WorkoutListLocalSource(_resources: Resources) : WorkoutListSource {
    private val resource: Resources = _resources

    override fun getWorkoutListByPart(type: BodyType): List<String> {
        return resource.getStringArray(type.getResourceId()).toList()
    }
}

这是我写的代码

但是这段代码一定是错误的。

开发者文档说 ViewModel 不应引用 Android platform

但是,我在 ViewModel.

中将 Resources 作为 argument 传递

我认为这部分是错误的,但我不知道如何正确修正它。


已更新

片段

class WorkoutListTabPageFragment : Fragment() {
    private var _binding : FragmentWorkoutListTabPageBinding? = null
    private val binding get() = _binding!!
    
    private val viewModel: WorkoutListViewModel by viewModels { WorkoutListViewModelFactory(resources) }

}

您可以使用 AndroidViewModel 而不是 ViewModel。如果你唯一的构造函数参数是应用程序,你甚至不需要为它创建一个工厂。

class WorkoutListViewModel(application: Application): AndroidViewModel(application) {
    private val resources = application.resources
    //...
}

以及代码简化提示:

fun setList(part : String) {
    _part.value = part
    _list.value = workoutListSource.getWorkoutListByPart(BodyType.valueOf(part))
}

尽管我认为拥有如此多的正文部分(将来可能会添加更多)有助于将类型作为存储库中的数据进行处理,而不是将它们硬编码为枚举值。无论哪种方式,最好承诺仅使用枚举或仅使用字符串,这样您就不必一直来回转换。

创建一个 ViewModelFactory class 并传入 ViewModel 的起始数据。

ViewModelFactory

class MyFragmentViewModelFacotry(private val resources: Resrouces) : ViewModelProvider.Factory {
  override fun<T : ViewModel?> create(modelClass: Class<T>): T {
    if(modelClass.isAssignableFrom(MyFragmentViewModel::class.java)) {
      return MyFragmentViewModel(resources) as T
    }
    throw IllegalArgumentException("Unknown ViewModel class")
  } 
}

视图模型

class ViewModel(private val resources: Resources) : ViewModel() {
   ...
}

使用 ViewModelFactory 创建 ViewModel,在 Activity 或 Fragment 运行 以下

val viewModelFactory: MyViewModelFactory = MyViewModelFactory(resources)
val viewModel =  ViewModelProvider(this, viewModelFactory).get(MyViewModel::class.java)