Text
Twitter: @ramonesteban78
Technical Lead en @WeAreBrintia
Blog: https://ramonesteban78.github.io/
Github: github.com/ramonesteban78
LinkedIn: es.linkedin.com/in/ramonesteban78
Demo Github: MarvelFormsReactUI
Indicar con nuestro código "que hacer" en vez de "como hacerlo"
Functional: Una función no tiene efectos secundarios. No existe un estado mutable en funciones
Reactive Programming: Los cambios se propagan en nuestro sistema de forma automática
FRP está basado en signals a las cuales nos podemos subscribir y podemos realizar procesos adicionales
Nosotros definimos las reglas y dejamos al sistema reaccionar ante las acciones del usuario
Proporciona las herramientas para construir programas asíncronos y basados en eventos
Hace uso del Observer design pattern sobre secuencias de eventos y/o datos
ReactiveX es como Linq, pero en vez de trabajar con IEnumerable, trabaja con IObervable, y resulta que los eventos se pueden observar
MVVM framework que utiliza Reactive Extensions dando lugar a un código elegante y testable
Inspirado en los principios de programación que aporta FRP
Objetivo: Hacer código entendible por humanos que da la casualidad que una máquina puede compilar
Funciona con otros frameworks como Xamarin.Forms, MvvmCross, etc.
Disponible para todas las tecnologías de UI de .Net
¿Es un framework o un conjunto de métodos de extensión de @ReactiveX?
Creador de ReactiveUI
Antiguo empleado de Github y actualmente trabajando en Slack
También conocido por: Akavache, ModernHttpClient, Splat, Refit, etc.
Github: github.com/paulcbetts
Como vemos INotifyPropertyChenged es al final un evento que lanza nuestro ViewModel. ¿Porqué no observar los eventos que vinculan nuestros ViewModels con la Vista y reaccionar a ellos con una serie de reglas definidas?
public interface INotifyPropertyChanged
{
//
// Events
//
event PropertyChangedEventHandler PropertyChanged;
}
Todos nuestros ViewModels deben de heredar de ReactiveObject, el cual implementa ya la interfaz INotifyPropertyChanged por nosotros
Importante: Todo el comportamiento y reglas de nuestro ViewModel las definimos en el constructor del mismo
public class ViewModelBase : ReactiveObject
{
public ViewModelBase()
{
this.SearchCharacters = ReactiveCommand.CreateFromTask<string>(
(text) => LoadData(text));
}
}
Nos permiten observar (observables) los cambios que se producen en las propiedades de nuestro ViewModel
// in the viewmodel
this.WhenAnyValue(x => x.SearchText)
.Where(x => !String.IsNullOrWhiteSpace(x))
.Throttle(TimeSpan.FromSeconds(.25))
.InvokeCommand(SearchCommand)
Si pensamos como haríamos esto con el paradigma de Mvvm tradicional, es como dejar de usar Linq y ponernos a recorrer colecciones con bucles for, dentro de otro bucle for, etc.
WhenAnyValue es una variante de WhenAny y hacen prácticamente lo mismo. La diferencia base es...
this.WhenAny(x => x.SearchText, x => x.Value)
this.WhenAnyValue(x => x.SearchText)
WhenAny se utiliza normalmente cuando tienes que trabajar con un framework o quieres hacer un método de extension, etc. Como regla general:
Utiliza siempre WhenAnyValue a no ser que sepas que necesitas WhenAny
Para más info: https://reactiveui.net/docs/handbook/when-any/
Read-Write Properties
string name;
public string Name {
get { return name; }
set { this.RaiseAndSetIfChanged(ref name, value); }
}
Read-Only Properties
// Since Commands should almost always be initialized
// in the constructor and never change, they are good
// candidates for this pattern
public ReactiveCommand<Object> PostTweet
{
get;
protected set;
}
Se tratan de propiedades que pueden ser informadas únicamente por un Observable
protected ObservableAsPropertyHelper<bool> _IsLoading;
public bool IsLoading => _IsLoading.Value;
this.SearchCharacters.IsExecuting
.ToProperty(this, x => x.IsLoading, out _IsLoading);
ToProperty es un método de extensión de ReactiveUI que informa que una propiedad del ViewModel ha cambiado y emite un signal a la vista.
ReactiveUI tiene su propia version de ICommand: ReactiveCommand
public ReactiveCommand SearchCharacters { get; protected set; }
this.SearchCharacters = ReactiveCommand
.CreateFromTask<string>((text) => LoadData(text));
ReactiveCommand es en un IObservable<object>. Esto nos permitirá utilizar toda la potencia de ReactiveX, por ejemplo para saber cuando se está ejecutando, que hacemos en caso de error, etc
ThrownExceptions \ IsExecuting
// Handle erros
this.SearchCharacters.ThrownExceptions
.Subscribe ((obj) => this.LogException(obj,
"Error while getting Marvel characters"));
// IsExecuting
this.SearchCharacters.IsExecuting
.ToProperty(this, x => x.IsLoading, out _IsLoading)
Con ReactiveCommand podemos controlar las posibles excepciones de la ejecución del mismo, así como definir un comportamiento mientras nuestro Command es ejecutado
OneWayBinding
var disp = this.OneWayBind(ViewModel, x => x.Name, x => x.Name.Text);
TwoWayBinding
this.Bind(ViewModel, x => x.Name, x => x.Name.Text);
BindCommand
this.BindCommand(ViewModel, x => x.OkCommand, x => x.OkButton);
Ventajas de usar Bindings en code-behind:
Funcionan de igual forma para todas las plataformas
Si cambias el nombre de una propiedad del ViewModel, tu proyecto no compila
Nos permiten observar (observables) los cambios que se producen en las propiedades de nuestro ViewModel
// in the viewmodel
this.WhenAnyValue(x => x.SearchText)
.Where(x => !String.IsNullOrWhiteSpace(x))
.Throttle(TimeSpan.FromSeconds(.25))
.InvokeCommand(SearchCommand)
Cuando subscribimos un objeto al evento que expone otro objeto introducimos un posible riesgo a que se produzcan memory leaks. ReactiveUI nos ofrece una variante del patrón Dispose para asegurarnos de que los Bindings son liberados por el GC
this.WhenActivated((CompositeDisposable disposables) =>
{
// Search text
this.Bind(ViewModel,
vm => vm.SearchText,
view => view.searchCharacters.Text)
.DisposeWith(disposables);
}
Es la versión de ObservableCollection de ReactiveUI
ReactiveUI recomienda el uso de Service Locator, en vez de inyectores de dependencias, pero puedes utilizarlas sin problema
ViewModel first navigation en Xamarin.Forms