Example of how to use MvxCachingFragmentActivity

2019-09-13 06:46发布

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

1条回答
放我归山
2楼-- · 2019-09-13 07:31

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.

查看更多
登录 后发表回答