Persist states after viewModelLifecyle till the app get closed

Viewed 24

I'm a beginner android developer and I got stuck with an issue.

viewModel keeps the states change data related to a fragment and when the user navigate to some fragment then the viewModel no longer keeps the states.

What I want is that when the user change something in the fragment and after that navigate to other fragment and then come back to the fragment where he changes something, he should see the changes he made.

Solutions are there for storing ex. shared_preference & Room, but my requirement is that I only want to keep the state data alive until the use closed the App.

I've googling so far but still didn't understand the approach developers follow to do these things. So can you also provide some guidance on approaches I should follow that consider the best practices. My main motive is to learn.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="homeViewModel"
            type="com.android.example.presentation.home.HomeViewModel" />
    </data>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".presentation.home.HomeFragment">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:keepScreenOn="true">

            <TextView
                android:id="@+id/sampleText"
                android:text="@{String.valueOf(homeViewModel.sampleText)}"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.5"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintVertical_bias="0.5" />

            <Button
                android:id="@+id/sampleButton"
                android:onClick="@{() -> homeViewModel.samplePressed()}"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="32dp"
                android:text="Button"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.5"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/sampleText" />


        </androidx.constraintlayout.widget.ConstraintLayout>

    </FrameLayout>

</layout>
class HomeViewModel : ViewModel() {
    private val _sampleText = MutableLiveData(0)
    val sampleText : LiveData<Int>
        get() = _sampleText

    fun samplePressed() {
        _sampleText.postValue(1)
    }
}

1 Answers

Thanks to the comment from Vivek Gupta

This can be achieved by scoping the ViewModel to the activity's lifecycle

previous

class HomeFragment : Fragment() {
    private val viewModel: HomeViewModel by viewModels()
}

Now change it this

class HomeFragment : Fragment() {
    private val viewModel: HomeViewModel by activityViewModels()
}

Edit: another way to do this if we have viewModelFactory

class HomeFragment : Fragment() {
    private lateinit var binding: FragmentHomeBinding
    private lateinit var mainRepository: MainRepository
    private lateinit var viewModel: HomeViewModel
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) : View {
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_home, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mainRepository = MainRepository(RetrofitInstance.api)
        val viewModelFactory = HomeViewModelFactory(mainRepository)
        viewModel = ViewModelProvider(requireActivity(), viewModelFactory).get(HomeViewModel::class.java)
        binding.homeViewModel = viewModel
        binding.lifecycleOwner = viewLifecycleOwner
    }
}
Related