4

I'm trying to use AndroidViewModel rather than the regular ViewModel, because AndroidViewModel contains an application reference that I need for binding services.

My question is, how do I supply the application parameter to my ViewModelFactory?

At the moment I'm casting it from the ApplicationContext that the ViewModelFactory injector util already has available to it, but I've read that's dangerous because a cast of ApplicationContext may not always return the application.

I'm just learning Android, following along the Sunflower example, so the answer is probably very simple. I just don't know it . . . yet. (Hoping you can help).

Here is how I am doing it currently, which as you may notice is closely based on how Google does it in the Sunflower example:

Fragment using the 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)
    ... 

Injector Util

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) {
...

My concern is inside the InjectorUtil, where I obtain a reference to the application by casting the applicationContext. If I proceed down that path am I heading for trouble down the line? Is there somewhere else I should be adding the application reference, where I can access it directly rather than through a cast of applicationContext?

thanks

John

John
  • 5,581
  • 6
  • 29
  • 46

0 Answers0