Currently I have a fragment class with a viewmodel being used in multiple activities. The viewmodel(viewModelOne) was added to be used in Activity1 but when Activity2 uses the fragment there is a runtime exception since the fragment's viewmodel is scoped to be used in the activity(eg. ViewModelProviders.of(getActivity()) and Activity2 doesn't instantiate viewModelOne. The easy solution is to create the viewModelOne instance in the Activity2 class but i am not a fan of this solution since viewModelOne is not relevant for this activity class. Any other solutions or recommendations?
Related
I am a bit of a noob attempting to pass data between a fragment (living inside a tab layout) and the activity that runs the fragment.
I have found a solution here, but I am unable to call the parent activity from the fragment.
Send data from activity to fragment in Android
Looking up multiple answers, they all say the same thing
CALL getActivity()!!
Call parent's activity from a fragment
It doesn't exist. I am using the Android.Support.V4.App.Fragment.
I can access a property this.Activity, but it's calling a random FragmentActivity when this is being hosted on an AppCompatActivity.
How can I access my hosting AppCompatActivity from the support Fragment?
I would suggest using viewmodels to pass data between activities and fragments
I've creating a test activity that updates some text in my MyViewModel.
I'd like to observe these changes in a Fragment, but when I use
MyViewModel myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
it gives me a different instance of MyViewModel than that used in the activity, which results in my onChanged() callback in the fragment not being called.
Only when I modify that same fragment code to
HomeViewModel homeViewModel = new ViewModelProvider(getActivity()).get(HomeViewModel.class);
does the fragment get the same instance of MyViewModel as the activity - so onChanged() is successfully called.
However, I'm not sure if using getActivity() as the ViewModelStoreOwner is the proper way of doing things as I haven't seen this in any examples anywhere. I'm wondering if there might be a better ViewModelStoreOwner I should be using in this instance?
I'm wondering if there might be a better ViewModelStoreOwner I should
be using in this instance?
You should use activity instance for sharing the same instance among fragments in the same activity.
Both Activity and Fragment implements their own ViewModelStoreOwner interface and implements the getViewModelStore() method. getViewModelStore() provide the ViewModelStore instance which is used to store the viewmodel objects, created by the ViewModelProvider.
Note: ComponentActivity implements the ViewModelStoreOwner interface and FragmentActivity (parent of AppCompatActivity) inherits the implementation.
So both Activity and Fragment have specific implementation for the ViewModelStoreOwner interface methods and store the viewmodel instance as per the lifecycle of the objects(including the configuration changes).
Since fragments belong to activity get the same activity instance so using the getActivity() will result in using the ViewModelStoreOwner object of the activity. To share the objects among fragments, simply use the activity instance for creating ViewModelProvider which will use the same ViewModelStoreOwner in all fragments hence will return the persisted object of viewmodel (if created before).
Having an Activity which does as little as possible has become a "best practice" for some time now, so the scenario of an Activity and a Fragment which need access to the same ViewModel instance may not be covered by many guides.
But "there is no rule without an exception", and your scenario is similar to the one where an Activity has two Fragments which need to share data.
In this case, one uses the Activity scope for the ViewModel to make sure every component will have access to the same instance. See also the section "Share data between fragments" in the View Model Overview at developer.android.com
I am trying to have my fragment (in a share module) comunicate with its parent activity.
I tried using the following code to call a callback in the parent activity
((MainActivity)getActivity())
I got a error saying MainActivity is undefined. I'm assuming this is because the fragment and Activity are in different modules. (NyLibary and app)
As it's in another module you'll need to import MainActivity class in your fragment.
By the way calling the parent activity this way is not the best thing you can do, in my opinion you should have interface represents the One who should implement your functions, this way you save the modularity for your fragment.
I would like to ask if it's correct to share the same ViewModel between Fragment and its Activity.I have UserDetailActivity and UserDetailFragment. Can I use the same ViewModel to display detail data of a user in the UserDetailActivity and UserDetailFragment or is there better approach.
Yes you can pass ViewModal object from a Activity to Fragment or vice-versa by implementing Parcelable into ViewModal class and can share object with fragment setArguments() method.
I am not using MVVM but I think its the same with MVP, I use the same Presenter(ViewModel in your case) with my Activity and its child Fragment. It make since because a Fragment is literally a fragment of an Activity. There might be some special cases where you really want to separate viewModel of Fragment and Activity, but most of the time, they share. About the initialization, dont pass your viewmodel directly, you can use dagger and inject it.
What is the advantage of using an interface to communicate from a fragment to an activity, as described here: http://developer.android.com/training/basics/fragments/communicating.html
This creates an unecessary dependency when we could have created an "onArticleSelected()" method in the activity WITHOUT THE INTERFACE and called it in the fragment via getActivity().onArticleSelected().
What if the activity, at another point in time contain a fragment where there are no articles, why create this illogical dependency and add more code?
Using an interface actually removes dependency on a specific Activity class. It allows the Fragment to work with any Activity that implements the interface, not just a single Activity.