Scenario: I need to create and load fragments dynamically (by code).
Example: I have a hierarchical data with categories and items, a category can contain items and other categories, like in Windows Explorer:
When user clicks on a folder icon, if it’s a folder, it will show the same view with folder’s child folders and items. If it’s an icon, we want to show just a label with the name of the item (in real-life, this can be rendering a document).
In Android, we will need
- an activity class and layout (or even a parent fragment) as host for the views. it will create and show the fragments dynamically by code,
- a fragment class and layout for the folder view (with a GridView)
- a fragment class and layout for the item view (with a TextView)
With MVVMCross, we will also have:
- a view-model class for the activity/parent fragment host
- a view-model class for the folder view
- a view-model class for the item view
With MVVM, when user clicks on a folder icon, the view-model is responsible to handle the event (by a Command) and trigger navigation to another fragment view, depending on the icon. But remember that the view-model must NOT directly instantiate and show the views, this is platform specific UI code.
In MVVMCross, we call MvxViewModel.ShowViewModel method to‘show’ the view-model. By default, what happens is, the MVVMCross finds the associated activity class (based on a name convention) and shows it. But In our case, this won’t work, because the view-models refer to fragments.
The solution is to use MVVMCross features to control the view creation mechanism.
MVVMCross has a built-in MvxAndroidViewPresenter class used to create and show an activity based on the view-model:
We can tell MVVMCross to use instead our own view presenter implementation which creates and shows fragments inside our activity or parent fragment.
The class is responsible for keeping a mapping between view-model types and the hosts which will instantiate and show the fragments.
We can now can register it for MVVMCross to use it, this being done in the Setup class in the Android app:
Note that the custom presenter once registered in MVVMCross, will be called for ANY view-model, whenever we call MvvmViewModel : ShowViewModel<T>();
ICustomPresenter and IFragmentHost are some simple interfaces we define in our code in order to nicely decouple the MVVMCross custom view presenter from the fragment host:
It makes sense for the activity class to implement the IFragmentHost interface:
Further more, we can have the activity have its own dictionary to keep a mapping between view-models and fragments, such that we can instantiate fragments based on the view-model class:
To make it reusable, we can even create a base class with this code, called for example MvxActivityFragmentHost and have the activity derive from it: