我想说你的直觉是正确地将图表实例移动到视图模型中,但是,正如你所指出的,当视图以外的对象需要上下文依赖关系时,它们可能会变得很麻烦。对我来说,这变成了依赖注入的问题,其中依赖是上下文,或者更广泛地说,是整个数据图表。我很想知道您如何获取视图模型,但我假设它依赖于 Android 视图模型提供程序(通过by viewModels()或某种方式ViewModelProvider.Factory)。
此问题的直接解决方案是将视图模型转换为AndroidViewModel通过视图模型的构造函数提供对应用程序上下文的引用的子类。虽然它仍然是一种反模式并且应该谨慎使用,但 Android 团队已经认识到某些用例是有效的。我个人不使用,AndroidViewModel因为我认为它是一个粗略的解决方案,否则可以通过改进依赖图来解决。但是,它是由官方文档批准的,这只是我的个人意见。根据经验,我必须说它的使用使得测试视图模型成为事后的噩梦。如果您对依赖注入库感兴趣,我强烈推荐Hilt最近推出稳定版的新实现1.0.0就在上个月发布。
撇开这一点不谈,我现在将为您的困境提供两种可能的解决方案:一种利用 the AndroidViewModel,另一种不利用。如果您的视图模型已经在上下文之外具有其他依赖项,则该AndroidViewModel解决方案不会为您节省太多开销,因为您可能已经ViewModelProvider.Factory在某个时候实例化了 a。这些解决方案将考虑 Android 的范围,但可以通过对生命周期钩子等进行一些调整轻松Fragment实现。ActivityDialogFragment
和AndroidViewModel
import android.app.Application
import androidx.lifecycle.AndroidViewModel
class MyViewModel(application: Application) : AndroidViewModel(application) {
val dataChart: DataChart
init {
dataChart = DataChart(application.applicationContext)
}
}
片段可能在哪里
class MyFragment : Fragment() {
private val viewModel: MyViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View { ... }
}
没有AndroidViewModel
import androidx.lifecycle.ViewModel
class MyViewModel(args: Args) : ViewModel() {
data class Args(
val dataChart: DataChart
)
val dataChart: DataChart = args.dataChart
}
片段可能在哪里
class MyFragment : Fragment() {
private lateinit var viewModel: MyViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val applicationContext: Context = requireContext().applicationContext
val dataChart = DataChart(applicationContext)
val viewModel: MyViewModel by viewModels {
ArgsViewModelFactory(
args = MyViewModel.Args(
dataChart = dataChart,
),
argsClass = MyViewModel.Args::class.java,
)
}
this.viewModel = viewModel
...
}
}
我自己的创作在哪里ArgsViewModelFactory,如下所示
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
class ArgsViewModelFactory<T>(
private val args: T,
private val argsClass: Class<T>,
) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T = modelClass.getConstructor(
argsClass,
).newInstance(
args,
)
}
编辑(通过 Hilt 模块):
@Module
@InstallIn(...)
object DataChartModule {
@Provides
fun provideDataChart(
@ApplicationContext context: Context,
): DataChart = DataChart(context)
}