user1202032 user1202032 - 3 months ago 23
C# Question

Simple 2 screen navigation in MvvmCross android app breaks back-button

I have made a very simple project using the latest MvvmCross version (4.2.3) in which i have 2 android screens: FirstView and SecondView. I use a button on FirstView to navigate to SecondView:

// FirstView.cs
private void PrepareShowSecondButton()
{
var hero = FindViewById<Button>(Resource.Id.firstview_show_second_button);
hero.Text = DreamsResources.FirstView_ShowSecond_Button_Label;
BindingSet.Bind(hero).To(vm => vm.ShowSecondCommand);
BindingSet.Apply();
}


// FirstViewModel.cs
private MvxCommand _showSecondCommand;

public MvxCommand ShowSecondCommand
{
get
{
_showSecondCommand = _showSecondCommand ?? new MvxCommand(DoShowSecondCommand);
return _showSecondCommand;
}
}

private void DoShowSecondCommand()
{
ShowViewModel<SecondViewModel>(new SecondViewModelBundle() { Data = "Hello from FirstView - " + Hello });
}


However, when I use the backbutton on the android device, and click the button to show SecondView again, SecondView is added multiple times (5-6) to the navigation stack. I have to click the back button so many times to get back to FirstView.

Code:

public class SecondViewModel : DreamsViewModelBase
{
private readonly IDreamsWebService _webService;

public SecondViewModel(IDreamsWebService webService)
{
_webService = webService;
}

public void Init(SecondViewModelBundle bundle)
{
Log.Log("Initializing with data: " + bundle.Data);
SecondData = bundle.Data;
}

private string _secondData;

public string SecondData
{
get { return _secondData; }
set { SetProperty(ref _secondData, value, "SecondData"); }
}
}


Layout:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_firstview_top_container_coordinatorlayout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
local:layout_scrollFlags="scroll|enterAlways"
local:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<LinearLayout
android:id="@+id/firstview_content_container_linearlayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize">
<EditText
android:id="@+id/firstview_edittext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="40dp" />
<TextView
android:id="@+id/firstview_textview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="40dp" />
<Button
android:id="@+id/firstview_show_second_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>


How do i avoid SecondView being added to the navigation stack multiple times? I've even tried setting the activity flag "SingleTop" which seems like a bad solution, and didnt even work.

Answer

On your project at GitHub you are calling the PrepareUI method on the onResume activity lifecycle callback. This adds (stacks) the same bindings every time the FirstView has been resumed (first time the app is opened, every time SecondView is closed). Thus, you end up with multiple bindings on the Show SecondViewModel button, which leads to opening the viewmodel several times.

There isn't a provided method that will clear the bindings, but you can do other things:

  1. create a new BindingSet object
  2. call your PrepareUI in the onCreate method
Comments