Introducción a ReactiveUI & Xamarin.Forms

Text

About me

Functional Reactive Programing

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

Ejemplo Reactive Programming

Nosotros definimos las reglas y dejamos al sistema reaccionar ante las acciones del usuario

Reactive Extensions

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

¿Quién utiliza ReactiveX?

¿Que es ReactiveUI?

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

Patrón MVVM

¿Que es ReactiveUI?

 

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?

Paul Betts

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

ReactiveUI

INotifyPropertyChanged

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;
}

ReactiveUI

ReactiveObject

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));
    }
}

ReactiveUI

WhenAny / WhenAnyValue

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.

ReactiveUI

WhenAny / WhenAnyValue

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/

ReactiveUI

Propiedades

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; 
}

ReactiveUI

Output Properties

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

Commands

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

Commands

ReactiveUI

Commands

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

ReactiveUI

Bindings

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

ReactiveUI

Converters

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)

ReactiveUI

WhenActivated

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);
}

ReactiveList

Es la versión de ObservableCollection de ReactiveUI

Splat - Locator

ReactiveUI recomienda el uso de Service Locator, en vez de inyectores de dependencias, pero puedes utilizarlas sin problema

ReactiveUI

And a lot more...

Routing

ViewModel first navigation en Xamarin.Forms

Demo

¿Preguntas?

Para reforzar con más calma...

Recursos

Thank you!!

Introducción a ReactiveUI con Xamarin.Forms

By Ramón Esteban

Introducción a ReactiveUI con Xamarin.Forms

Functional Reactive Programming for .Net developers

  • 448
Loading comments...

More from Ramón Esteban