Search code examples
androidandroid-fragmentsmvvmandroid-databindingandroid-mvvm

Add fragment from ViewModel in MVVM architecture


I am using DataBinding and following MVVM architecture, now i am stuck on how to add new fragment from ViewModel as we need defined click event on ViewModel. Here is my MainViewModel class

public class MainViewModel {
    private Context context;

    public MainViewModel (Context context) {
        this.context = context;
    }
    public void onClick(View v) {

    }
}

here is my xml where i have defined click event

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="viewmodel"
            type="com.example.MainViewModel" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
         <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{viewmodel::onClick}"
            android:text="click me"/>
    </RelativeLayout>
</layout>

now how can i get supportFragmentManager or childFragmentManager from my ViewModel class? I have tried to use activity.getSupportFragmentManager() and activity.getChildFragmentManager() but it doesn't have that kind of method.

I know we can add fragment with following code

getActivity().getSupportFragmentManager().beginTransaction()
            .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out).
            add(R.id.container, fragment, "").addToBackStack("main").commit();

but how to do it in ViewModel class


Solution

  • Since you have your Context available, you have two possibilities:

    public class MainViewModel {
        private Context context;
    
        public MainViewModel (Context context) {
            this.context = context;
        }
    
        public void onClick(View v) {
            //use context:
            ((AppCompatActivity) context).getSupportFragmentManager();
    
            //OR use the views context:
            if(v.getContext() instanceof AppCompatActivity) {
                ((AppCompatActivity) v.getContext()).getSupportFragmentManager();
            }            
        }    
    }
    

    It may be useful to check whether the context is an instance of your activity (like MainActivity) or AppCompatActivity, or if it is null before calling any method.