how to instantiate ViewModel In AndroidX?

[亡魂溺海] 提交于 2020-03-18 11:27:20

问题


I want to initialize ViewModel in Activity using androidx library

I have tried what documentation says but it is not working. the ".of" is not resolved.

import androidx.appcompat.app.AppCompatActivity

import android.os.Bundle import androidx.databinding.DataBindingUtil import androidx.lifecycle.ViewModelProvider import com.example.myapplication.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val binding: ActivityMainBinding = DataBindingUtil.setContentView(
        this, R.layout.activity_main)
    binding.setLifecycleOwner(this)

    var model = ViewModelProvider.of(this).get(SheduleViewModel::class.java)

}

}

of is not resolved, may be there are other way to do it in androidx


回答1:


Updated answer:

Things changed a little bit, as the previously needed dependency - ViewModelProviders - got deprecated (see the old answer for details). You can now use the ViewModelProvider constructor directly.

So, in this case, the answer would be:

private val viewModel = ViewModelProvider(this).get(SheduleViewModel::class.java)

Note that, however, if you're instantiating a ViewModel in a Fragment, you can add the androidx.fragment:fragment-ktx:$Version dependency and then make use of property delegation:

private val viewModel: SheduleViewModel by viewModels()

Which internally will use ViewModelProvider and scope your ViewModel to your Fragment. It's just a more concise way of writing the same thing.

Both the ViewModelProvider constructor and by viewModels() also accept a factory as a parameter (useful for injecting your ViewModel):

private val viewModel = 
    ViewModelProvider(this, viewModelFactory).get(SheduleViewModel::class.java)

and

private val viewModel: SheduleViewModel by viewModels { viewModelFactory }

Use the one that best suits you.

Old answer:

Add the androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionsVersion dependency in order to import ViewModelProviders.




回答2:


(How to) Use ViewModel from Android Architecture Component :

  1. Add the Google Maven repository (Optional, just verify that)

    Android Studio projects aren't configured to access this repository by default.

    To add it to your project, open the build.gradle file for your project (not the ones for your app or module) and add the google() repository as shown below:

    allprojects {
        repositories {
            google()
            jcenter()
        }
    }
    
  2. Declaring dependencies

    Open your app-level build.gradle file,

    Go to dependencies{} block

    Put implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version" for AndroidX version, $lifecycle_version here is latest version defined.

    For Pre-AndroidX use implementation "android.arch.lifecycle:viewmodel:1.1.1" (1.1.1 is the last version from this artifact i guess.)

  3. In your activity, use like this syntax

    Import this class :

    import androidx.lifecycle.ViewModelProviders; for AndroidX

    import android.arch.lifecycle.ViewModelProviders; when using Pre-AndroidX

    And obtain your ViewModel like following

    ViewModelProviders.of(this).get(ProfileObservableViewModel::class.java) // Kotlin syntax

    ---- or ----

    ViewModelProviders.of(this).get(ProfileObservableViewModel.class); // Java syntax




回答3:


Updating ViewModel to Lifecycle Version 2.2.0 and Above

The ViewModels (VMs) may theoretically be initialized as class level instance variables using the Kotlin extension library import androidx.fragment.app.viewModels method by viewmodels(). By initializing the VM as a class level instance var it can be accessed within the class.

Question: Is there a downside to initializing the VMs as class level instance variables instead of inside onCreate?

When creating the VMs with the extension function inside onCreate the VMs are only scoped within onCreate and extra code is required to reassign the class level instance variables.

See documentation

  • ViewModel Overview
  • Lifecycle

Initialize VM as Class Instance Val

class Fragment : Fragment() {
    private val viewModel: SomeViewModel by viewModels()

    private fun observeViewState() {
        viewModel.feedViewState.observe(viewLifecycleOwner) { viewState ->
            //viewState used here.
        }
    }
}

Initialize VM in onCreate and Reassign Class Instance Var

class Fragment : Fragment() {
    private lateinit var viewModel: SomeViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val viewModel: ContentViewModel by viewModels()
        this.viewModel = viewModel
    }

    private fun observeViewState() {
        viewModel.feedViewState.observe(viewLifecycleOwner) { viewState ->
            //viewState used here.
        }
    }
}

Passing Arguments/Parameters

// Override ViewModelProvider.NewInstanceFactory to create the ViewModel (VM).
class SomeViewModelFactory(private val someString: String): ViewModelProvider.NewInstanceFactory() {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T = SomeViewModel(someString) as T
} 

class SomeViewModel(private val someString: String) : ViewModel() {
    init {
        //TODO: Use 'someString' to init process when VM is created. i.e. Get data request.
    }
}

class Fragment: Fragment() {
    // Create VM in activity/fragment with VM factory.
    val someViewModel: SomeViewModel by viewModels { SomeViewModelFactory("someString") } 
}

Enabling SavedState with Arguments/Parameters

class SomeViewModelFactory(
        private val owner: SavedStateRegistryOwner,
        private val someString: String) : AbstractSavedStateViewModelFactory(owner, null) {
    override fun <T : ViewModel?> create(key: String, modelClass: Class<T>, state: SavedStateHandle) =
            SomeViewModel(state, someString) as T
}

class SomeViewModel(private val state: SavedStateHandle, private val someString: String) : ViewModel() {
    val feedPosition = state.get<Int>(FEED_POSITION_KEY).let { position ->
        if (position == null) 0 else position
    }

    init {
        //TODO: Use 'someString' to init process when VM is created. i.e. Get data request.
    }

     fun saveFeedPosition(position: Int) {
        state.set(FEED_POSITION_KEY, position)
    }
}

class Fragment: Fragment() {
    // Create VM in activity/fragment with VM factory.
    val someViewModel: SomeViewModel by viewModels { SomeViewModelFactory(this, "someString") } 
    private var feedPosition: Int = 0

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        someViewModel.saveFeedPosition((contentRecyclerView.layoutManager as LinearLayoutManager)
                .findFirstVisibleItemPosition())
    }    

    override fun onViewStateRestored(savedInstanceState: Bundle?) {
        super.onViewStateRestored(savedInstanceState)
        feedPosition = someViewModel.feedPosition
    }
}


来源:https://stackoverflow.com/questions/54313453/how-to-instantiate-viewmodel-in-androidx

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!