Comments 21
Все-таки Xamarin.Forms и Xamarin.iOS+Xamarin.Android — существенно отличаются с точки зрения разработчика. Поэтому, для большей объективности сравнения фреймворков следовало бы описать и процесс реализации указанного ТЗ и на Xamarin.iOS+Xamarin.Android. Но авторам эксперимента все равно спасибо за более-менее объективное сравнение фреймворков, а то слишком уж «холиварная» тема.
+1
Кстати, в предыдущей статье был комментарий о сборке приложения под iOS на Windows. Насколько я знаю, это невозможно. Хотелось спросить у автора — вам известно что-то об этом?
+1
Либо сделайте свойства классов Note, Project только для чтения, либо добавьте в них INotifyPropertyChanged. Иначе будут утечки памяти через PropertyDescriptor (если команда Xamarin не переделала нутро биндингов при портировании WPF на мобилы).
В WPF у биндингов по умолчанию выставлялся режим TwoWay. Это означало, что CLR должен как-то реализовать оповещение изменения свойства в обе стороны. Если нет INotify… то CLR вынужден создавать в памяти спец. прокси, реализующие событие изменения свойства. И хранятся эти прокси в таблице рутовых хэндлов, к которым явного доступа для разраба нет.
Использовать POCO-объекты во ViewModel — короткий путь отстрелить себе все возможные колени. Особенно с ListView и ItemTemplate с биндингом. Крутите список, контейнеры айтемов создаются и выбрасываются. Но GC их собрать не может, т.к. они держатся в памяти через PropertyDescriptor. Удачи в отладке утечек памяти в мобиле :)
В WPF у биндингов по умолчанию выставлялся режим TwoWay. Это означало, что CLR должен как-то реализовать оповещение изменения свойства в обе стороны. Если нет INotify… то CLR вынужден создавать в памяти спец. прокси, реализующие событие изменения свойства. И хранятся эти прокси в таблице рутовых хэндлов, к которым явного доступа для разраба нет.
Использовать POCO-объекты во ViewModel — короткий путь отстрелить себе все возможные колени. Особенно с ListView и ItemTemplate с биндингом. Крутите список, контейнеры айтемов создаются и выбрасываются. Но GC их собрать не может, т.к. они держатся в памяти через PropertyDescriptor. Удачи в отладке утечек памяти в мобиле :)
+1
Просто процитирую текст из статьи: «Все классы моделей и вью моделей будут реализовывать интерфейс INotifyPropertyChanged. Его реализацию в приводимых примерах кода я уберу для лаконичности.»
0
В условиях дефицита времени читал по диагонали. Думаю, найдется много новичков которые просто скопипастят, обнаружат, что апп работает, а потом в далеком будут гадать почему апп крашится с OutOfMemory.
Для длинного кода есть спойлеры, если что.
Для длинного кода есть спойлеры, если что.
0
Согласен, тут скорее вопрос стилистики статьи. Мне не очень нравится, когда куча кода под спойлерами. Если можно вставить короткий кусок кода, но inline, то мне кажется это будет чуть более читабельно. А для копирования мы специально репу сделали. Но, еще раз повторюсь, я не претендую на то, что мой подход самый правильный.
0
Реализация 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);
}
}
0
Ещё можно взять Fody и страшный шаблонный код совсем исчезнет.
[AddINotifyPropertyChangedInterface]
public class ExampleViewModel
{
// И backing field, и уведомления
// оно реализует само, за нас.
public string Title { get; set; }
}
Либо можно взять ReactiveUI.Fody, кому как нравится.
0
Здравствуй, boxing-unboxing
0
Использовать POCO-объекты во ViewModel — короткий путь отстрелить себе все возможные колени.
Можете этот тезис поподробнее осветить. Только открываю мир WPF И MVVM, поэтому было бы интересно ваше мнение.
0
[del] форма ввода коммента задублировала…
0
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».
+5
А если сравнить скорость работы этих двух приложений(Kivy. Xamarin.Forms), какое из них будет быстрее работать?
0
Sign up to leave a comment.
Kivy. Xamarin. React Native. Три фреймворка — один эксперимент (часть 2)