Androidxライブラリを使用してアクティビティの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)
}
}
のは解決されていません。androidxで他の方法がある可能性があります
更新された回答:
以前必要だった依存関係-ViewModelProviders
- get deprecated のように、状況は少し変更されました(詳細については以前の回答を参照してください)。 ViewModelProvider
コンストラクタを直接使用できるようになりました。
したがって、この場合、答えは次のようになります。
_private val viewModel = ViewModelProvider(this).get(SheduleViewModel::class.Java)
_
ただし、ViewModel
をFragment
にインスタンス化している場合は、_androidx.fragment:fragment-ktx:$Version
_依存関係を追加してから、プロパティの委任を利用できます。
_private val viewModel: SheduleViewModel by viewModels()
_
どちらが内部的にViewModelProvider
を使用し、ViewModel
をFragment
にスコープします。同じことを書くためのより簡潔な方法です。
ViewModelProvider
コンストラクターとby viewModels()
のどちらも、パラメーターとしてファクトリーを受け入れます(ViewModel
を挿入するのに便利です):
_private val viewModel =
ViewModelProvider(this, viewModelFactory).get(SheduleViewModel::class.Java)
_
そして
_private val viewModel: SheduleViewModel by viewModels { viewModelFactory }
_
自分に最適なものを使用してください。
古い答え:
ViewModelProviders
をインポートするには、_androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionsVersion
_依存関係を追加します。
(方法)ViewModel
fromAndroid Architecture Component:
Google Mavenリポジトリを追加します(オプション、それを確認してください)
Android Studioプロジェクトは、デフォルトではこのリポジトリにアクセスするように設定されていません。
それをプロジェクトに追加するには、プロジェクトの_build.gradle
_ファイルを開きます(アプリまたはモジュールのファイルではありません)とgoogle()
レポジトリを以下に示します。
_allprojects {
repositories {
google()
jcenter()
}
}
_
依存関係の宣言
アプリレベルの_build.gradle
_ファイルを開き、
_dependencies{}
_ブロックに移動
AndroidXバージョンの_implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
_を入れて、$ lifecycle_versionここで定義されている最新バージョンです。
AndroidXより前の場合_implementation "Android.Arch.lifecycle:viewmodel:1.1.1"
_を使用します(1.1.1はこのアーティファクトの最後のバージョンです)
あなたの活動では、この構文のように使用してください
このクラスをインポート:
_import androidx.lifecycle.ViewModelProviders;
_ forAndroidX
_import Android.Arch.lifecycle.ViewModelProviders;
_Pre-AndroidXを使用する場合
そして、あなたのViewModel
を次のように入手してください
ViewModelProviders.of(this).get(ProfileObservableViewModel::class.Java)
// Kotlin構文
----または----
ViewModelProviders.of(this).get(ProfileObservableViewModel.class);
// Java構文
ViewModels(VM)は、理論的にはKotlin拡張ライブラリ_import androidx.fragment.app.viewModels
_メソッドby viewmodels()
を使用してクラスレベルのインスタンス変数として初期化できます。 VMをクラスレベルのインスタンス変数として初期化することにより、クラス内でアクセスできます。
質問:VMをonCreate
の内部ではなくクラスレベルのインスタンス変数として初期化することにはマイナス面がありますか?
onCreate
内に拡張関数を使用してVMを作成する場合、VMのスコープはonCreate
内に限定され、クラスレベルのインスタンス変数を再割り当てするには追加のコードが必要です。
ドキュメントを見る
_class Fragment : Fragment() {
private val viewModel: SomeViewModel by viewModels()
private fun observeViewState() {
viewModel.feedViewState.observe(viewLifecycleOwner) { viewState ->
//viewState used here.
}
}
}
_
_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") }
}
_
_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
}
}
_