为AndroidViewModel创建ViewModelFactory的正确方法是什么

时间:2018-07-18 04:59:52

标签: android dependency-injection kotlin android-viewmodel

我正在尝试使用AndroidViewModel而不是常规的ViewModel,因为AndroidViewModel包含绑定服务所需的应用程序引用。

我的问题是,如何为我的ViewModelFactory提供应用程序参数?

此刻,我正在从ApplicationContext强制转换它,而ViewModelFactory注入器实用程序已经可以使用它了,但是我读到这很危险,因为强制转换为ApplicationContext may not always return the application

我只是按照Sunflower example学习Android,所以答案很简单。我只是不知道。 。 。然而。 (希望您能提供帮助)。

这是我当前的操作方式,您可能会注意到,这与Google在向日葵示例中的操作方式密切相关:

使用AndroidViewModel的片段

class GalleryFragment : Fragment() {

private lateinit var viewModel: GalleryViewModel
private var memoList: List<Memo> = emptyList()

override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
): View? {
    val view = inflater.inflate(R.layout.gallery_fragment, container, false)
    val context = context ?: return view
    val factory = InjectorUtils.provideGalleryViewModelFactory(context)
    viewModel = ViewModelProviders.of(this, factory).get(GalleryViewModel::class.java)
    ... 

进样器实用程序

object InjectorUtils {

fun provideMemoViewModelFactory(context: Context, memoId: Long): MemoViewModelFactory {
    val application = context.applicationContext as Application //this could be dangerous
    val repository = getMemoRepository(context)
    return MemoViewModelFactory(application, repository, memoId)
   }
}

ViewModelFactory

class MemoViewModelFactory(
    private val application: Application,
    private val memoRepository: MemoRepository,
    private val memoId: Long
 ) : ViewModelProvider.NewInstanceFactory() {

@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
    return MemoViewModel( application, memoRepository, memoId) as T
  }
}

ViewModel

class MemoViewModel(
    application: Application,
    memoRepository: MemoRepository,
    private val memoId: Long
) : AndroidViewModel(application) {
...

我关心的是InjectorUtil内部,在这里我通过投射applicationContext获得对应用程序的引用。如果我沿着那条路走下去,我是否会遇到麻烦?我应该在其他地方添加应用程序引用,在那里我可以直接访问它,而不是通过applicationContext的强制转换?

谢谢

约翰

1 个答案:

答案 0 :(得分:0)

我在这里看到两种解决方案:

  1. 使用Dagger,这将注入所有必需的依赖项(包括Application)。您可以阅读有关如何将Dagger与AAC ViewModel Factory here结合使用的更多信息。

  2. 第二种解决方案是将Application实例存储为静态变量,并在需要时访问它,例如Application.get()。考虑到Application对象还是单例。