Update - Thanks to @Martijn00 and @Plac3Hold3r I have managed to update my app to use the MvxCachingFragmentCompatActivity but it is just not working correctly. I am finding that if I go back sometimes the the ViewModel will be available, but the commands in the view model will be null.
Also if I go back and then forward, some of the buttons don't respond. I assume this is the same issue.
What I really need to know is what the additional functionality the caching activity gives me, and how to use it properly.
Original question follows...
I am hitting a problem where the view model for a fragment is null. I suspect my activity is being cleared up when I open a camera activity. For all my application am using a single activity and all my views are fragments.
When the camera activity is complete, the activity is reconstructed, but one of the fragments view model is null. I am currently using an AppCompatActivity for my single activity, but through my research I should probably be using a MvxCachingFragmentActivity. The problem is I have no idea how I am supposed to use it. I cannot find a clear explanation anywhere.
Has anyone got a working example of how to use the MvxCachingFragmentActivity or the MvxCachingFragmentCompatActivity.
I can't find anywhere where it tells me how I should use it.
I found this other link example but I think it is out of date and the other link given in this example is a 404.
If anyone knows of a simple sample and whether this will work with a single activity please let me know.
Thanks
Setup
MainActivity
Create an activity that inherits from MvxCachingFragmentCompatActivity
or MvxCachingFragmentActivity
.
[Activity]
public class MainActivity : BaseFragmentActivity<MainContainerViewModel>
{
}
MainContainerViewModel
Create a Viewmodel to associate to the Activity. You will never navigate directly using this Viewmodel. Instead you will navigate to this Viewmodel via the fragments that specifies MainContainerViewModel
as their parent's Viewmodel.
public class MainContainerViewModel : MvxViewModel
{
}
XML layout example
Add a layout to your MainActivity
. Make sure to include a FrameLayout
that has an id. In this case content_frame
. This id is important as this is how you will identify the frame where to place your fragment. You specify multiple FrameLayout's
if you want more that one fragment for the same view.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary">
<TextView
android:id="@+id/textview_toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:layout_gravity="left"
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
HomeFragment
In terms of fragments you need to include the MvxFragment
attribute, which needs the type of Viewmodel associate to the Activity you want to place your fragment in. Additionally, you need to specify the id for the FrameLayout
that is found on the activities layout, where you want to place the fragment.
[MvxFragment(typeof(MainContainerViewModel), Resource.Id.content_frame)]
[Register(nameof(HomeFragment))]
public class HomeFragment : BaseFragment<HomeViewModel>
{
}
Usage
When navigating your can now use ShowViewModel<HomeViewModel>()
which will navigate to the home fragment. But, importantly it will first start up the required Activity MainActivity
before doing the fragment navigation. This allows for better shared navigation with other platforms which do not require these container Viewmodels, i.e. they get handled automatically via convention.
Notes
You can specify multiple MvxFragment
attributes. Is is usefully if you want the same fragment shared under multiple Activities. The Top MvxFragment
attribute will be used as the default. If you are currently in the context of any of the other matching MvxFragment
attributes then navigation will take place under that activity.
If your Setup.cs is not inheriting from MvxAppCompatSetup
or you are using a custom presenter, you need to make sure that you also registering your presenter against IMvxAndroidViewPresenter
. This is important as MvxCachingFragmentCompatActivity
or MvxCachingFragmentActivity
resolve IMvxAndroidViewPresenter
in order to navigate to the required fragment.
protected override IMvxAndroidViewPresenter CreateViewPresenter()
{
var mvxFragmentsPresenter = new MvxFragmentsPresenter(AndroidViewAssemblies);
Mvx.RegisterSingleton<IMvxAndroidViewPresenter>(mvxFragmentsPresenter);
return mvxFragmentsPresenter;
}
You can also check out the Sample Repo for an example of this in use.