Answer the question
In order to leave comments, you need to log in
Migration to MVVMcross, how to do it right?
Good afternoon, we are developing an iMonitoring application on a self-made MVVM architecture.
In the general core, we have a model class ViewM, a model controller ViewControllerMC which has methods and events. The ViewControllerVC view controller subscribes to these events, in which work with the UI of each of the platforms is already taking place.
Those. the schema is ViewM <-> ViewControllerMC <---> ViewControllerVC.
ViewControllerVC on iOS is derived from UIViewController, while on Android it is a separate ViewControllerVC class.
And the issue of migration lies precisely in it.
The main idea is that the ViewControllerVC, as it were, corresponds to UIViewControllerVC and can include child ViewControllerVCs. Android Activity and fragments act as containers into which the root ViewControllerVCs are inserted (more precisely, the views controlled by them are Android Views). Each ViewControllerVC works with a specific model and has its own View (RelativeLayout, FrameLayout, LinearLayout) with which it fumbles, listening to signals from the model.
I present this class below.
public class ViewControllerVC : IViewAndroidController
{
private ViewControllerMC modelController;
private NavigationItemVC navigationItemVC;
private Activity activity;
public ViewControllerVC(Activity activity)
{
IsDestroyed = false;
this.activity = activity;
}
public ViewControllerVC(Activity activity, ViewControllerMC model, View view = null)
{
IsDestroyed = false;
this.activity = activity;
if (view == null)
{
// есть базовый алгоритм загрузки View, но его можно перекрыть
view = LoadBaseView(model);
}
if (view != null)
{
SetControlledView(view, model.View);
BindWithModel(model);
}
}
public event EventHandler ViewWillDestroy;
/// <summary>
/// Если NavigationController == null то операции Push, Present реализуют запуск ВьюКонтроллера в новом Активити (ContentActivity.cs),
/// если не null то обращаются к NavigationController чтобы он открыл вьюху и вьюКонтрллер в
/// своем окне поверх текщуего вьюКонтроллера через AddView(...).
/// </summary>
/// <value>Навгационный контроллер</value>
public NavigationVC NavigationController { get; set; }
public string ModelUUID { get; private set; }
public Activity Activity
{
get
{
return activity;
}
}
public ViewVC View { get; private set; }
public View BaseRootView
{
get
{
if (View != null)
{
return View.View;
}
return null;
}
}
protected ViewControllerMC ModelController
{
get
{
return GetModelController();
}
private set
{
SetModelController(value);
}
}
// устанавливаем подконтрольную вьюху и потом ищем в ней нужные контролы
public void SetControlledView(View view, ViewMC model)
{
View = new ViewVC(Activity, model, view);
}
public virtual void BindWithModel(ViewControllerMC model)
{
if (IsAliveModel)
{
UnbindFromModelController();
}
ModelController = model;
ModelUUID = ModelController.UUID;
FindViews();
InitByModel();
ApplyDefaultInterfaceSettings();
LocalizeUserInterface();
SubscribeToViewEvent();
SubscribeToModelEvent();
}
public virtual void AddViewToParent(View parentView)
{
if (View == null || View.View == null)
{
return;
}
var currentParent = (ViewGroup)View.View.Parent;
if (currentParent != null)
{
if (!ReferenceEquals(currentParent, parentView))
{
currentParent.RemoveView(View.View);
}
else
{
return;
}
}
if (parentView is ViewGroup)
{
(parentView as ViewGroup).AddView(View.View, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent));
}
}
public void HideSoftInput(IBinder binder)
{
if (!IsDestroyed)
{
var inputManager = (InputMethodManager)Activity.GetSystemService(Activity.InputMethodService);
inputManager.HideSoftInputFromWindow(binder, 0);
}
}
public void ShowSoftInput(View view, ShowFlags flags)
{
var inputManager = (InputMethodManager)Activity.GetSystemService(Activity.InputMethodService);
inputManager.ShowSoftInput(view, flags);
}
public virtual void RemoveFromParent()
{
// здесь удаляется представление из родителя, андроид это позволяет.
// а удаление из словаря родителя CompilanceControllers.Remove(controller.ModelController), если необходимо,
// происходит по дополнительному запросу события от чилда AskRemoveControllerFromParent() в перекрытом этом методе
// а также в перекрытом методе анимируем чилд относительно роидителя как хотим.
// Можно не удалять а скрывать за экарн.
// бывает ситуация когда вьюха уже уничтожена,
// и после этого по событию окончания анимации срабатывает удаление вьюхи с экрана
if (View == null || View.View == null)
{
return;
}
View.RemoveFromParentView();
}
protected virtual View LoadBaseView(ViewControllerMC model)
{
View view = null;
var layoutId = ResourceHelper.GetIdByName(model.ViewControllerId);
if (layoutId > 0)
{
view = activity.LayoutInflater.Inflate(layoutId, null);
}
return view;
}
protected virtual void InitByModel()
{
InitNavigationItem();
PresentationStyle = WindowPresentationStyle.Center;
}
protected virtual void FindViews()
{
}
protected virtual void SubscribeToModelEvent()
{
ModelController.WillDestroy += HandleWillDestroy;
ModelController.InsetViewChanged += HandleInsetViewChanged;
ModelController.FromParentViewControllerRemoved += HandleFromParentViewControllerRemoved;
ModelController.ViewDestroyed += HandleModelControllerViewDestroyed;
ModelController.Dismissed += HandleViewControllerDismissed;
//// ModelController.IsEditingChanged += HandleModelControllerIsEditingChanged;
ModelController.ViewOverlaid += HandleViewOverlaid;
ModelController.ViewControllerPresented += HandleViewControllerPresented;
ModelController.PopoverControllerChaned += HandlePopoverControllerChaned;
//// ModelController.CultureChanged += HandleCultureChanged;
ModelController.InSightChanged += HandleModelControllerInSightChanged;
}
protected virtual void UnsubscribeFromModelEvent()
{
ModelController.WillDestroy -= HandleWillDestroy;
ModelController.InsetViewChanged -= HandleInsetViewChanged;
ModelController.FromParentViewControllerRemoved -= HandleFromParentViewControllerRemoved;
ModelController.ViewDestroyed -= HandleModelControllerViewDestroyed;
ModelController.Dismissed -= HandleViewControllerDismissed;
ModelController.ViewOverlaid -= HandleViewOverlaid;
ModelController.ViewControllerPresented -= HandleViewControllerPresented;
ModelController.PopoverControllerChaned -= HandlePopoverControllerChaned;
ModelController.InSightChanged -= HandleModelControllerInSightChanged;
}
protected virtual void SubscribeToViewEvent()
{
View.View.ViewAttachedToWindow += HandleViewAttachedToWindow;
View.View.ViewDetachedFromWindow += HandleViewDetachedFromWindow;
}
protected void SafetyInvokeOnMainThread(Action action)
{
if (IsDestroyed)
{
return;
}
if ((Activity != null) && (action != null))
{
Activity.RunOnUiThread(action);
}
}
private void PresentViewController(ViewControllerMC model)
{
ViewControllerFactory.Instance.RunDialogContainerByModelSafety(App.Instance.ActivityInstance, model);
}
}
}
Answer the question
In order to leave comments, you need to log in
In general, the ViewControllerMc model in our architecture, as I understand it, is an analogue of MvxViewModel,
the controller is for iOs MvxViewController and for android MvxActivity.
But MvxActivty is suitable for us only for the root of the general page, but all the children included inside - how they can be released so that they also work with MvxViewModel models. As I already said, is it possible to add your own type, inherit ViewControllerVC from IMvxAndroidView and create your own presenter for it.
I will give another example to understand our architecture. For example, there is a home screen and in it we add a title. In code it looks like this:
public class HomeScreenVC : ViewControllerVC
{
public HomeScreenVC(Activity activity, ViewControllerMC model) : base(activity, model)
{
}
public HomeScreenTopBarVC TopBar { get; set; }
protected override void InitByModel()
{
base.InitByModel();
TopBar = (HomeScreenTopBarVC)ViewControllerFactory.Instance.GetOrCreateViewControllerByModel(Activity, ModelController.TopBar, BaseRootView.FindViewById<LinearLayout>(Resource.Id.HomeTopBarLayout));
}
...
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question