Как стать автором
Обновить

Комментарии 21

Все-таки Xamarin.Forms и Xamarin.iOS+Xamarin.Android — существенно отличаются с точки зрения разработчика. Поэтому, для большей объективности сравнения фреймворков следовало бы описать и процесс реализации указанного ТЗ и на Xamarin.iOS+Xamarin.Android. Но авторам эксперимента все равно спасибо за более-менее объективное сравнение фреймворков, а то слишком уж «холиварная» тема.
Для этого надо иметь опыт на тех платформах, ну или на нативе. Я iOS немного знаю, а в Android ни в зуб ногой :)
Кстати, в предыдущей статье был комментарий о сборке приложения под iOS на Windows. Насколько я знаю, это невозможно. Хотелось спросить у автора — вам известно что-то об этом?
Поисследовал подробнее. Да, все не так радужно, как я писал ранее, извиняюсь за дезинформацию. Для разработки конечных приложений будет нужна хостовая MacOS машина. Мы же у себя разрабатываем компоненты под Xamarin.Forms. Вот их можно билдить и под Windows. Поправил текст статьи.
Либо сделайте свойства классов Note, Project только для чтения, либо добавьте в них INotifyPropertyChanged. Иначе будут утечки памяти через PropertyDescriptor (если команда Xamarin не переделала нутро биндингов при портировании WPF на мобилы).

В WPF у биндингов по умолчанию выставлялся режим TwoWay. Это означало, что CLR должен как-то реализовать оповещение изменения свойства в обе стороны. Если нет INotify… то CLR вынужден создавать в памяти спец. прокси, реализующие событие изменения свойства. И хранятся эти прокси в таблице рутовых хэндлов, к которым явного доступа для разраба нет.

Использовать POCO-объекты во ViewModel — короткий путь отстрелить себе все возможные колени. Особенно с ListView и ItemTemplate с биндингом. Крутите список, контейнеры айтемов создаются и выбрасываются. Но GC их собрать не может, т.к. они держатся в памяти через PropertyDescriptor. Удачи в отладке утечек памяти в мобиле :)
Просто процитирую текст из статьи: «Все классы моделей и вью моделей будут реализовывать интерфейс INotifyPropertyChanged. Его реализацию в приводимых примерах кода я уберу для лаконичности.»
В условиях дефицита времени читал по диагонали. Думаю, найдется много новичков которые просто скопипастят, обнаружат, что апп работает, а потом в далеком будут гадать почему апп крашится с OutOfMemory.

Для длинного кода есть спойлеры, если что.
Согласен, тут скорее вопрос стилистики статьи. Мне не очень нравится, когда куча кода под спойлерами. Если можно вставить короткий кусок кода, но inline, то мне кажется это будет чуть более читабельно. А для копирования мы специально репу сделали. Но, еще раз повторюсь, я не претендую на то, что мой подход самый правильный.
Уместно реализацию ViewModelBase спрятать в спойлер, а в конкретных ViewModel лаконичность кода не изменится (см. мой коммент ниже).
Да, как вариант.
Реализация ViewModelBase
public class ViewModelBase : INotifyPropertyChanged
{
    private readonly Dictionary<string, object> _properties = new Dictionary<string, object>();

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected void SetValue<T>(T value, [CallerMemberName] string propertyName = null)
    {
        if (!_properties.ContainsKey(propertyName))
        {
            _properties.Add(propertyName, default(T));
        }

        var oldValue = GetValue<T>(propertyName);
        if (!EqualityComparer<T>.Default.Equals(oldValue, value))
        {
            _properties[propertyName] = value;
            OnPropertyChanged(propertyName);
        }
    }

    protected T GetValue<T>([CallerMemberName] string propertyName = null)
    {
        if (!_properties.ContainsKey(propertyName))
        {
            return default(T);
        }

        return (T)_properties[propertyName];
    }
}


Пример использования в конкретной ViewModel
public class MainViewModel : ViewModelBase, IUpdateTrackConfig
{
    #region Fields
    //...
    #endregion //Fields

    #region Properties

    public ObservableCollection<ViewModelBase> Pages { get; } = new ObservableCollection<ViewModelBase>(new ViewModelBase[]
    {
        new DashboardViewModel(), 
        new SoundSettingsViewModel(), 
        new InertialSettingsViewModel()
    });

    public DashboardViewModel Dashboard { get; }

    // Вот так лучше сразу показывать даже в примерах / статьях
    public string Version
    {
        get => GetValue<string>();
        set => SetValue(value);
    }

}


Ещё можно взять Fody и страшный шаблонный код совсем исчезнет.


[AddINotifyPropertyChangedInterface]
public class ExampleViewModel 
{
    // И backing field, и уведомления
    // оно реализует само, за нас.
    public string Title { get; set; }
}

Либо можно взять ReactiveUI.Fody, кому как нравится.

Здравствуй, boxing-unboxing
если команда Xamarin не переделала нутро биндингов при портировании WPF на мобилы
Нет. Хотите «портировать WPF на мобилы» — используйте сторонние реализации паттерна MVVM, которые работают и на WPF, и на Xamarin. Например, MVVMCross
Xamarin.Forms я и назвал портом WPF на мобилы в данном случае
:)
Использовать POCO-объекты во ViewModel — короткий путь отстрелить себе все возможные колени.


Можете этот тезис поподробнее осветить. Только открываю мир WPF И MVVM, поэтому было бы интересно ваше мнение.
public class MyLabel : Label {
    protected override void OnPropertyChanged([CallerMemberName] string propertyName = null) {
        base.OnPropertyChanged(propertyName);

        if (propertyName == "Text") {
            ((this.Parent as MyCellGrid).Parent as Cell).ForceUpdateSize();
        }
    }
}


Для решения этой проблемы уместнее использовать Behavior. Этот зверь можно сделать более универсальным, чтобы иметь возможность навешивать его не только на Label.
Behavior может быть таргетом биндинга на любое количество свойств VM, а также он хранит ссылку на UI элемент. Соответственно, с его помощью можно гибко настраивать поведение UI элемента без жесткой привязки к конкретному свойству «Text».

Да, конечно. Это будет более красиво.
А если сравнить скорость работы этих двух приложений(Kivy. Xamarin.Forms), какое из них будет быстрее работать?
Не сравнивали, мы не ставили себе подобной задачи, а потому и не копали в этом направлении. Хотя я не думаю, что на столь простом приложении мы бы смогли получить какие-то серьезные результаты.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий