How to implement by viewModels?
Asked Answered
S

2

8

I have been trying to implement the LiveData and View Model. In this App, a number is displayed on the screen and we can add five or minus one. Now Earlier I used viewModelProvider but now it is deprecated and I am using "by viewmodels" but it is showing ann error

fragOne.kt

class fragOne : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        var binding = DataBindingUtil.inflate<FragmentFragoneBinding>(
            inflater,
            R.layout.fragment_fragone,
            container,
            false
        )

        //viewModel = ViewModelProviders.of(this).get(fragViewModel::class.java)
        // Create the observer which updates the UI.
        val viewModel: fragViewModel by **viewModels()**
        val nameObserver = Observer<Int> {
            viewModel.num.value=it

        }
        // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
        viewModel.num.observe(viewLifecycleOwner,nameObserver)
        // setting on Click listener for add button
        binding.add.setOnClickListener()
        {

            //updateNumber()
            viewModel.num.setValue(viewModel.addFive())
        }

        // setting on on Click Listener for minus button
        binding.minus.setOnClickListener()
        {
            viewModel.num.setValue(viewModel.minusOne())
            //updateNumber()
        }


        return binding.root
    }

        // Always call the superclass so it can save the view hierarchy state
}

fragViewModel

import androidx.lifecycle.ViewModel

class fragViewModel:ViewModel()
{
    val num: MutableLiveData<Int> by lazy {
        MutableLiveData<Int>()
    }
    // Initializing num=0
    init {
         num .value= 0
    }
    // Functions to add five or subtract one

    fun addFive():Int
    {
        var newNumber:Int?=num.value

        return newNumber?.plus(5)?:0
    }

     fun minusOne():Int
    {
        var newNumber:Int?=num.value

        return newNumber?.minus(1)?:0
    }
}

In fragOne there is an error showing in by viewModels . So whats the error. please let me know if anyone wants the code I will upload it in Github

build.gradle

    def lifecycle_version = "2.2.0"
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.core:core-ktx:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation "androidx.core:core-ktx:1.2.0"
    // ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"


}
Septime answered 4/3, 2020 at 14:33 Comment(12)
You're asking us "what's the error", but you're the one that can see it, not us. Can you post what the error says? My guess is you're missing the Ktx Fragments dependency in your build.gradle file.Carranza
I have updated itSeptime
and added the dependencies in my question, please tell me what is missingSeptime
You're still missing the Fragments Ktx library, which is the one with by viewModels. implementation "androidx.fragment:fragment-ktx:1.2.2"Carranza
I will apply it and let you knowSeptime
After I added there was another error showing cannot inline...... which I than converted jvm from 1.6 to 1.8 now there is an error Cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option I am not getting a solution for thisSeptime
You need kotlinOptions { jvmTarget = "1.8" } in the android block in build.gradle.Carranza
Sir, I used what you said, now when I play the app it is showing an warning viewmodelprovider deprecated and also the screen is blankSeptime
You're describing code that you haven't posted, so I don't know what's wrong. Your code above doesn't use ViewModelProvider. I also noticed that you were trying to use by viewModels inside the onCreateView method. You can only use property delegates at the property declaration, not for local variables.Carranza
I know I haven't used ViewModelProviders but It is showing a warning and for the second statement are you saying that I would use lateint in declaring by viewmodelsSeptime
Should I send you the codeSeptime
You can edit your question or start a new one. Read the language docs about property delegates to understand how it works. It is not lateinit.Carranza
A
11

Since you are using a fragment in addition implementation "androidx.core:core-ktx:1.3.1" adding this to your build.gradle implementation "androidx.fragment:fragment-ktx:1.2.5"

Usage in Fragment

// 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>()
Alkahest answered 7/8, 2020 at 3:16 Comment(0)
O
0

First add the the following dependencies to use viewModels(), (latest version)

implementation("androidx.navigation:navigation-fragment-ktx:$nav_version")
implementation("androidx.navigation:navigation-ui-ktx:$nav_version")
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"

Then you can use in your fragment

private val yourViewModel: YourViewModel by viewModels { // scope is this fragment      
 YourViewModelFactory(YourRepository(YourItemDatabase.invoke(requireContext())))
}

Or

private val yourViewModel: YourViewModel by activityViewModels()// scope is it's activity
Othilia answered 21/1, 2022 at 17:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.