旋转时与视图模型的旧实例绑定的片段视图(Android-MVVMCross)

时间:2018-09-21 12:17:02

标签: c# android android-fragments mvvmcross

在我的应用程序中,我有一个活动,并且默认情况下需要加载MvxFragment。该片段有一个按钮,单击该按钮将弹出一个MvxDialogFragment。当我在对话框中单击“是”时,应在片段中更新文本。

当对话框弹出时,如果我旋转然后按“是” ,则该片段中的文本没有得到更新。

我正在Activity ViewModel的ViewAppeared()方法中加载MvxFragment。 以下是代码段:

活动ViewModel:

 public class FirstViewModel
    : MvxViewModel
{
    public FirstViewModel()
    {
        Console.WriteLine("Firstviewmodel : Ctor()");
    }

    public override void ViewAppeared()
    {
        Console.WriteLine("Firstviewmodel : ViewAppeared()");
        Mvx.Resolve<IMvxNavigationService>().Navigate<FragmentAViewModel>();

        base.ViewAppeared();
    }
    public override void ViewCreated()
    {
        Console.WriteLine("Firstviewmodel : ViewCreated()");

        base.ViewCreated();
    }
    public override void ViewAppearing()
    {
        Console.WriteLine("Firstviewmodel : ViewAppearing()");
        base.ViewAppearing();
    }

活动布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:id="@+id/toolbar_layout">
    <include
        android:id="@+id/toolbar"
        layout="@layout/toolbar"
        local:layout_scrollFlags="scroll|enterAlways" />
</android.support.design.widget.AppBarLayout>
<FrameLayout
    android:id="@+id/content_frame"
    android:background="#FFFFFF"
    android:layout_below="@id/toolbar_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

片段布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#008080">
<TextView
    android:layout_width="match_parent"
    android:layout_height="50dp"
    local:MvxBind="Text FragmentAText" />
<Button
    android:layout_width="match_parent"
    android:text="Click"
    android:layout_height="35dp"
    local:MvxBind="Click ShowDialogCommand" />
</LinearLayout>

片段(.cs)文件:

 [MvxFragmentPresentationAttribute(typeof(FirstViewModel), 
  Resource.Id.content_frame)]
[Register("androidMVVMTest.droid.views.fragmentA")]

public class FragmentAView :MvvmCross.Droid.Support.V4.MvxFragment
{
    public FragmentAViewModel Model
    {
        get
        {
            return (FragmentAViewModel)ViewModel;
        }
    }
    public override void OnCreate(Bundle savedInstanceState)
    {
        Console.WriteLine("Fragment A : OnCreate()");
        RetainInstance = true;
        base.OnCreate(savedInstanceState);
    }

    public override View OnCreateView(LayoutInflater inflater, ViewGroup 
    container, Bundle savedInstanceState)
    {

        Console.WriteLine("Fragment A : OnCreateView()");
        base.OnCreateView(inflater, container, savedInstanceState);
        return this.BindingInflate(Resource.Layout.FragmentA, null);
    }

FragmentViewModel:

 public class FragmentAViewModel:MvxViewModel
{
    public Action ShowDialog;
    private string _fragmentAText;
    public string FragmentAText
    {
        get
        {
            return _fragmentAText;
        }
        set
        {
            _fragmentAText = value;
            RaisePropertyChanged(() => FragmentAText);
        }
    }
    public FragmentAViewModel()
    {
        Console.WriteLine("FragmentAViewModel : Ctor()");
    }
     public IMvxCommand ShowDialogCommand
    {
        get
        {

            return new MvxCommand(() =>
            {

                  Mvx.Resolve<IMvxNavigationService>().Navigate<DialogViewModel,Dictionary<string,object>>(PrepareDialogNavigationParams(ChangeName));
            });
        }
    }
    private Dictionary<string, object> PrepareDialogNavigationParams(Action operationType)
    {
        Dictionary<string, object> dialogNavigationParams = new Dictionary<string, object>();
        dialogNavigationParams.Add("operation", operationType);
        return dialogNavigationParams;
    }
    private void ChangeName()
    {
        FragmentAText = "Hello!!!";
    }

DialogFragmentViewModel:

 public class DialogViewModel : MvxViewModel<Dictionary<string,object>>
{
    public Action RequestedOperation;

    public IMvxCommand ExecuteYesCommand
    {
        get
        {
            return new MvxCommand(() =>
            {
                RequestedOperation?.Invoke();
                MvvmCross.Platform.Mvx.Resolve<IMvxNavigationService>().Close(this);
            }
            );
        }
    }

   public override void Prepare(Dictionary<string, object> parameter)
    {
        RequestedOperation = parameter["operation"] as Action;
    }
}

假定片段中的文本在持久性存储中已更新。这样一来,就可以从中获取

旋转时,正在创建片段视图模型的新实例。这可能是由于在FirstViewModel的ViewAppeared()方法中使用导航服务加载了片段。但是,我在FragmentA.cs中给出了RetainInstance = true。

由于RetainInstance为true,因此仅存在一个片段视图实例,但是在旋转时,有两个片段视图模型实例。

我的查询是:

  1. 片段绑定到哪个viewmodel实例?
  2. 如何避免在旋转时避免视图模型的多个实例并在活动中加载默认片段?

0 个答案:

没有答案