web-dev-qa-db-ja.com

AndroidXでViewModelをインスタンス化する方法

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で他の方法がある可能性があります

12

更新された回答:

以前必要だった依存関係-ViewModelProviders- get deprecated のように、状況は少し変更されました(詳細については以前の回答を参照してください)。 ViewModelProviderコンストラクタを直接使用できるようになりました。

したがって、この場合、答えは次のようになります。

_private val viewModel = ViewModelProvider(this).get(SheduleViewModel::class.Java)
_

ただし、ViewModelFragmentにインスタンス化している場合は、_androidx.fragment:fragment-ktx:$Version_依存関係を追加してから、プロパティの委任を利用できます。

_private val viewModel: SheduleViewModel by viewModels()
_

どちらが内部的にViewModelProviderを使用し、ViewModelFragmentにスコープします。同じことを書くためのより簡潔な方法です。

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_依存関係を追加します。

18

(方法)ViewModel fromAndroid Architecture Component

  1. Google Mavenリポジトリを追加します(オプション、それを確認してください)

    Android Studioプロジェクトは、デフォルトではこのリポジトリにアクセスするように設定されていません。

    それをプロジェクトに追加するには、プロジェクトの_build.gradle_ファイルを開きます(アプリまたはモジュールのファイルではありません)google()レポジトリを以下に示します。

    _allprojects {
        repositories {
            google()
            jcenter()
        }
    }
    _
  2. 依存関係の宣言

    アプリレベルの_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はこのアーティファクトの最後のバージョンです)

  3. あなたの活動では、この構文のように使用してください

    このクラスをインポート:

    _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構文

3
Jeel Vankhede

ViewModelを Lifecycleバージョン2.2. 以上に更新する

ViewModels(VM)は、理論的にはKotlin拡張ライブラリ_import androidx.fragment.app.viewModels_メソッドby viewmodels()を使用してクラスレベルのインスタンス変数として初期化できます。 VMをクラスレベルのインスタンス変数として初期化することにより、クラス内でアクセスできます。

質問:VMをonCreateの内部ではなくクラスレベルのインスタンス変数として初期化することにはマイナス面がありますか?

onCreate内に拡張関数を使用してVMを作成する場合、VMのスコープはonCreate内に限定され、クラスレベルのインスタンス変数を再割り当てするには追加のコードが必要です。

ドキュメントを見る

初期化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.
        }
    }
}
_

OnCreate VM in onCreateと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.
        }
    }
}
_

引数/パラメーターを渡す

_// 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
Adam Hurwitz