如何在AndroidX中实例化ViewModel?

时间:2019-01-22 17:23:10

标签: android viewmodel android-jetpack

我想使用androidx库在Activity中初始化ViewModel

我已经尝试了文档中所说的内容,但是没有用。 “ .of”无法解析。

import androidx.appcompat.app.AppCompatActivity

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

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尚未解决,可能还有其他方法可以在androidx中实现

6 个答案:

答案 0 :(得分:9)

将ViewModel更新到Lifecycle Version 2.2.0及以上

ViewModels (VM)理论上可以使用Kotlin扩展库import androidx.fragment.app.viewModels方法by viewmodels()初始化为类级实例变量。通过将VM初始化为类级别的实例var,可以在类中对其进行访问。

问题:将VM初始化为类级实例变量而不是在onCreate内有不利之处吗?

onCreate内部使用扩展功能创建VM时,VM仅在onCreate范围内,并且需要额外的代码来重新分配类级实例变量。

请参阅文档

将VM初始化为类实例Val

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

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

在onCreate中初始化VM并重新分配类实例变量

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.
        }
    }
}

传递参数/参数

// 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") } 
}

启用带参数/参数的SavedState

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
    }
}

答案 1 :(得分:3)

PS。这是给使用Java并像我一样卡住了一段时间的人提供的,这样的答案一直在Google中出现。

显然,截至该日期(2020年5月6日),API发生了变化,我必须这样做才能使其正常工作。

// 1. Create a ViewModel Class Let's call it AppStateViewModel

// 2. Put below code Inside Activity onCreate like this:
ViewModelProvider.Factory factory = new ViewModelProvider.NewInstanceFactory();
appStateManager = new ViewModelProvider(this, factory).get(AppStateViewModel.class);

答案 2 :(得分:2)

添加androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionsVersion依赖项以导入ViewModelProviders

答案 3 :(得分:1)

(操作方法)使用 Android体系结构组件中的ViewModel

  1. 添加Google Maven存储库(可选,只需验证一下即可)

    默认未将Android Studio项目配置为访问此存储库。

    要将其添加到您的项目中,请打开项目build.gradle文件(而不是您的应用程序或模块的文件),然后添加 google() < / strong>存储库,如下所示:

    allprojects {
        repositories {
            google()
            jcenter()
        }
    }
    
  2. 声明依赖项

    打开您的应用级build.gradle文件,

    转到 dependencies{}

    为{strong> AndroidX 版本,{strong> $ lifecycle_version 版本输入implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"是这里定义的最新版本。

    对于Android X之前的版本,请使用implementation "android.arch.lifecycle:viewmodel:1.1.1" (我猜这是该工件的最新版本1.1.1。)

  3. 在您的活动中,使用这种语法

    导入此类:

    import androidx.lifecycle.ViewModelProviders; for AndroidX

    import android.arch.lifecycle.ViewModelProviders;在使用 Android X之前的版本

    并按照以下步骤获取ViewModel

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

    ----或----

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

答案 4 :(得分:1)

ViewModelProviders:不推荐使用此类。直接将构造函数用于ViewModelProvider。

科特林

中的示例

这是直接使用ViewModelProvider的方式:

如果您的视图模型仅使用一个参数(应用程序)扩展了 AndroidViewModel ,则您可以使用默认的AndroidViewModelFactory,而不必编写新工厂。示例:

// Activity / fragment class
private lateinit var viewModel: MyOwnAndroidViewModel

    // onCreate
    viewModel = ViewModelProvider(
            this,
            ViewModelProvider.AndroidViewModelFactory(application)
        ).get(MyOwnAndroidViewModel::class.java)

如果您的视图模型仅扩展了 ViewModel 而没有额外的参数,请使用NewInstanceFactory()

// Activity / fragment class
private lateinit var viewModel: MyOwnViewModel

    // onCreate
    viewModel = ViewModelProvider(
            this,
            ViewModelProvider.NewInstanceFactory()
        ).get(MyOwnViewModel::class.java)

上述亚当的答案也涵盖了其他变化形式。

免责声明:仍在学习基础的Android开发-如果代码有任何问题,请在评论中告诉我。

答案 5 :(得分:1)

对我来说,唯一有效的方法:

implementation 'androidx.fragment:fragment:1.2.4'