Anmol
Anmol

Reputation: 8670

how to get viewModel by viewModels? (fragment-ktx)

I am working with Single viewModel for the Activity and all of its fragment.

So to initialise viewmodel if have to write this setup code in onActivityCreated of all the fragment's

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProviders.of(activity!!).get(NoteViewModel::class.java)
    }

I was going thorough the Android KTX extension page:(refer here)

and i found i can initialise view model like this:

    // Get a reference to the ViewModel scoped to this Fragment
    val viewModel by viewModels<MyViewModel>()

    // Get a reference to the ViewModel scoped to its Activity
    val viewModel by activityViewModels<MyViewModel>()

So I added below dependency's to my gradle(app):

    //ktx android
    implementation 'androidx.core:core-ktx:1.0.2'
    implementation 'androidx.fragment:fragment-ktx:1.0.0'
    implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"

But when i try to use viewModels/activityViewModels in my application their reference in not found.

I want help in how to use these extension's with some basic example i tried searching for examples haven't found any.

Upvotes: 152

Views: 140904

Answers (14)

ONVETI
ONVETI

Reputation: 472

UPDATE 2025 JANUARY 18


You should use this:

Groovy

dependencies {
    implementation "androidx.fragment:fragment-ktx:1.8.5"
}

Kotlin KTS

dependencies {
    implementation("androidx.fragment:fragment-ktx:1.8.5")
}

more information:

  1. https://developer.android.com/kotlin/ktx#fragment

  2. https://developer.android.com/topic/libraries/architecture/viewmodel#implement

Upvotes: 21

Hassan El Sayed Ammer
Hassan El Sayed Ammer

Reputation: 137

this happened because you forgot to add this dependency.

to solve this issue add this dependency

 implementation 'androidx.activity:activity-ktx:1.3.1'

and hit Sync

Upvotes: 0

htafoya
htafoya

Reputation: 19283

Be sure to use val and not var for your ViewModel property if you get error of cannot find setter.

Upvotes: 3

Anmol
Anmol

Reputation: 8670

Atlast we we have got stable version.

After moving to implementation 'androidx.fragment:fragment-ktx:1.1.0' i faced another issue.

Compiler Error:

Cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6

build.gradle (Module :app)

compileOptions {
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
}

kotlinOptions {
    jvmTarget = "1.8"
}

reference

After applying all the above the issue's is resolved.

Upvotes: 119

Abdulsalam Al-Hammadi
Abdulsalam Al-Hammadi

Reputation: 197

You can fix it by implementing the fragment-ktx library like this

def fragment_version = "1.4.0"

implementation("androidx.fragment:fragment-ktx:$fragment_version")

See more and check latest version here.

Upvotes: 1

Bekzhan
Bekzhan

Reputation: 585

I think you need to have this dependency for your activity if you want to use kotlin delegations for viewmodel

//ViewModels delegation extentensions for activity
implementation 'androidx.activity:activity-ktx:1.3.1'

Upvotes: 38

Evgenii Vorobei
Evgenii Vorobei

Reputation: 1569

For googlers: your Activity should inherit AppCompatActivity, not Activity

Upvotes: 3

Rishad Baniya
Rishad Baniya

Reputation: 755

Note : This works for Jetpack Compose too

Copy the dependency from HERE

Currently 2021 June 5 the dependency is as below :

dependencies {
    val activity_version = "1.2.3"

    // Java language implementation
    implementation("androidx.activity:activity:$activity_version")
    // Kotlin
    implementation("androidx.activity:activity-ktx:$activity_version")
}

Upvotes: 3

user11729434
user11729434

Reputation: 711

try

implementation 'androidx.fragment:fragment-ktx:1.1.0-beta02'

2021 UPDATE

This is no longer in beta. It works with the latest stable version at the time of writing. You will also need to import it in your fragment's Kotlin file.

implementation 'androidx.fragment:fragment-ktx:1.3.2'
import androidx.fragment.app.activityViewModels

Upvotes: 71

Apps Developer
Apps Developer

Reputation: 31

Try this one. It works for me.

implementation "androidx.fragment:fragment-ktx:1.2.5"

Upvotes: 1

midFang
midFang

Reputation: 135

You can implementation

implementation 'androidx.fragment:fragment-ktx:1.1.0'

In fact, the BY viewModels implementation in the KTX package looks like this, and you might as well implement an extension function yourself

@MainThread
inline fun <reified VM : ViewModel> ComponentActivity.viewModels(
        noinline factoryProducer: (() -> ViewModelProvider.Factory)? = null
): Lazy<VM> {
    val factoryPromise = factoryProducer ?: {
        val application = application ?: throw IllegalArgumentException(
                "ViewModel can be accessed only when Activity is attached"
        )
        ViewModelProvider.AndroidViewModelFactory.getInstance(application)
    }

    return ViewModelLazy(VM::class, { viewModelStore }, factoryPromise)
}

Upvotes: 2

Blundell
Blundell

Reputation: 76564

If you have come here looking for a solution for Koin:

Note you can use use Koin to make this work:

private val viewModel by viewModel<NoteViewModel>()

would use the import

import org.koin.android.viewmodel.ext.android.viewModel

from the dependency:

implementation "org.koin:koin-android-viewmodel:+" // change + to w/e is the latest when u read this

Upvotes: -6

sylvery
sylvery

Reputation: 180

The extension function viewModels(...) was added in version 1.1.0-alpha03. Therefore, in order to use it in your app you will have to implement the fragment-ktx of versions matching 1.1.0-alpah03 or later.

I just found out about this and so I resorted to using version 1.1.0-rc01 because I didn't want to use alpha/beta versions.

Upvotes: 2

Birju Vachhani
Birju Vachhani

Reputation: 6373

You use this latest alpha version:

dependencies {
    implementation 'androidx.fragment:fragment-ktx:1.2.0-alpha01'
}

Upvotes: 3

Related Questions