Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Struggle to get the same ViewModel instance

I'm not sure if I understand ViewModel architecture correctly in Android. I suppose ViewModel lifecycle is tie to the activity so we are expecting the same instance and it doesn't matter if we are passing the activity or fragment context to ViewModelProvider?

Anyway, here's my ViewModel:

class MainViewModel : ViewModel() {
    var teamName: String = "Warriors";
}

Here's my Activity:

class MainActivity : AppCompatActivity() {
    private lateinit var viewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
        viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)

        viewModel.teamName = "Cavaliers";
        Log.d("YouQi", "activity viewModel.teamName: ${viewModel.teamName}");

        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                    .replace(R.id.container, MainFragment.newInstance())
                    .commitNow()
        }
    }
}

and lastly here's my Fragment:

class MainFragment : androidx.fragment.app.Fragment() {
    companion object {
        fun newInstance() = MainFragment()
    }

    private lateinit var viewModel: MainViewModel

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        return inflater.inflate(R.layout.main_fragment, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
        Log.d("YouQi", "fragment viewModel.teamName: ${viewModel.teamName}");
    }

}

I'm getting the below output in Logcat:

2018-06-03 16:06:24.591 31124-31124/com.axzae.zapkotlin D/YouQi: activity viewModel.teamName: Cavaliers
2018-06-03 16:06:24.652 31124-31124/com.axzae.zapkotlin D/YouQi: fragment viewModel.teamName: Warriors

It shows the value did not update to Cavaliers. am I using ViewModel wrongly and should be using Dagger to achieve singleton?

like image 863
You Qi Avatar asked Oct 24 '25 14:10

You Qi


2 Answers

It does matter what ViewModelProvider are you using - from activity or from fragment. Please try to use ViewModelProviders.of(getActivity()) for fragment.

That's actually very handy - you can keep fragment-related model and more general activity-bound model separately.

like image 191
kzotin Avatar answered Oct 27 '25 05:10

kzotin


No, you don't need to use Dependency injection to achieve singleton in ViewModel. You can pass the activity context to the ViewModel like this:

viewModel = ViewModelProviders.of(activity).get(MainViewModel::class.java)// by this you will get the same value of teamName as your activity
like image 37
Keshav Aggarwal Avatar answered Oct 27 '25 03:10

Keshav Aggarwal