Fundamentals of Dart Streams

Welcome to part 2 of my series on Flutter Architecture:

  • Introduction
  • Fundamentals of Dart Streams (this post)
  • RxDart: Magical transformations of Streams
  • RxVMS foundations: RxCommand and GetIt
  • RxVMS: Services & Managers
  • RxVMS: The self responsible widget
  • User Authentication the RxVMS way

Streams are the main building block of RxVMS so we will take a closer look at them in this post because understanding Streams is an absolute requirement to understand RxVMS.

It turned out that including Rx in this post would make it too long so I split it two parts.

Let it flow

I read a lot of comments that say Streams and especially Rx is too hard to understand, so they don’t use it.

I like you to know is that I don’t count myself a Rx wizard. Mastering the full power of Rx is not easy I admit that and I’m still learning. But let me set right one misconception from the beginning: You don’t have to be an Rx wizard to gain a lot of benefits using Streams and Rx. I will try to do my best to explain Streams as easy as I can.

What are Streams?

For me, the best analogy for a Stream is a conveyor belt. You can put an item on one side and it will automatically be transported to the other. Streams act like a conveyor belts, but instead of physical items we can put a data object on the belt and it will transport them automatically, but to where? Well, as with a real conveyor, if noone is there to catch them at the end then the items will just drop off and get lost. (Ok, this isn’t entirely true with Dart Streams but it’s best to treat Streams as if it were.)

stream_no_listener

To avoid having your data object drop off into the void you can set up a “trap” at the end of a Stream. The trap will catch any arriving object and do something (react) each time it catches an item that reaches the end of the belt.

stream_listener

Remember:

  • When your data reaches the end of your Stream, if you haven’t set up a trap to handle that even then your data will fall off into the void and never be seen again. (Again, not entirely true with Dart Streams but you’re better off pretending it is.)

  • After putting an object on the Stream you don’t wait for it to reach the end because the Stream will handle all of that in the background.

  • Your trap can receive an item at anytime; it doesn’t have to happen right after you put something on the Stream (don’t worry Streams transport Data really fast). Imagine you don’t know how fast the belt moves or how long it is. This means putting something on a Stream is completely decoupled from reacting on an item at the other end. Your trap will trigger and catch the item whenever it gets there. (Some of you might already realize that this fits nicely into the reactive way that Flutter updates its Widgets.)

  • You can setup a trap long before the first item will arrive.

  • It’s “First In First Out”. Items will always come out in the same order they went in.

And what is Rx?

Rx, short for Reactive Extensions, are Streams on steroids 😉 Rx is a concept very similar to Streams that was invented for the .net framework by a team at Microsoft. As .net already had a type Stream that is used for file I/O, they named them Observables and created a lot of functions to manipulate the data that moves through them. Dart has Streams embedded in its language specification which already offer a lot of this functionality, but not all of it. That’s why the RxDart package was developed; it’s based on Dart Streams, but takes things further by extening their functionality. Wie will take a closer look at Rx in the next part of this series.

Some nomenclature

Dart Streams and Rx use some nomenclature that can look a bit scary, so here’s a translation. I’ll show Dart first, then Rx.

  • Stream/Observable This is the conveyor belt discussed above. A Stream can always be converted to an Observable and you can assign Observables anywhere you use a Stream. So don’t get confused if I use these terms interchangeably.

  • listen/subscribe Setting the “trap”.

  • StreamController/Subject The “left” side of the conveyor belt, where you put data on the Stream. The two differ slightly in their properties and features, but serve the same purpose.

  • Emitting an item/data The moment when data appears at the end of the conveyor belt.

Creating Streams

If you want to follow along with the following chapters, please clone this project for the basic Stream examples. I’ll be using the Dart/Flutter testing system.

To create a Stream you have to create a StreamController

var controller = new StreamController<String>();

controller.add("Item1"); // Put first item on the belt

The generic type (in this case String) that has to be passed when creating a StreamController defines which type of objects we can push onto the Stream. This can be ANY type! You can create a StreamController<List<MyObject>>() if you want to, and it will transport a whole List instead of single objects.

Building the trap

If you run the test above, then nothing will visibly happen because there’s nothing at the end to catch your Strings. So, lets create a trap:

var controller = new StreamController<String>();


controller.stream.listen((item) => print(item)); // this is the trap

controller.add("Item1");
controller.add("Item2");
controller.add("Item3");

Now we’ve got the trap set, using the .listen() method on the stream of the StreamController. It’s written “controller.stream.listen” but if you run it backward, like a record album from the 60’s, it’s real meaning will be revealed. “Listen to the Stream with this Controller.”

You have to pass a function into the .listen() method because it needs to know what to do when it “hears” something (when a new data object arrived at the end of the Stream). This function that you’re passing in needs to accept a parameter that is of the same type the StreamController was created with. In this case, it was a String: new StreamController<String>();

If you run the above code it will output:

Item1
Item2
Item3
✓ Setting the trap
Exited

In my opinion the biggest problem for people who are new to Streams is that you can define the reaction for an emitted item long before the first item is is pushed on the stream that causes that reaction to get called.

Stop listening

The above code example omitted a small but important part. listen() is a function that returns a StreamSubscription object. Calling .cancel() on it frees the subscription, preventing your listening function from being called after you want to cancel it:

var controller = new StreamController<String>();

StreamSubscription subscription = controller.stream.listen((item) => print(item)); // This is the Trap

controller.add("Item1");
controller.add("Item2");
controller.add("Item3");

// This is to prevent the testing framework from killing this process 
// before all items from the Stream have been taken care of
await Future.delayed(Duration(milliseconds: 500));

subscription.cancel;

Listen to the details

As wrote above, listen() expects a function that takes a parameter, and this parameter needs to be of the same type that the StreamController was created with. This function can be a lambda, like in the example above, or it can be any other function.

The following are all valid examples:

void myPrint(String message) {
  print(message);
}

StreamSubscription subscription = controller.stream.listen((item) => print(item)); // using a lambda function

StreamSubscription subscription2 = controller.stream.listen(myPrint); // using tear-off

StreamSubscription subscription3 = controller.stream.listen((item) {
    print(item);
    print(item.toUpperCase);
}); // using lambda block

Important: Most Dart Streams are single subscription streams, meaning that after they’ve listened once they can’t listen a second time without throwing an exception. This is different than other implementations of Rx

The full signature of listen() looks like this:

    /* excerpt from the API doc
   * The [onError] callback must be of type `void onError(error)` or
   * `void onError(error, StackTrace stackTrace)`. If [onError] accepts
   * two arguments it is called with the error object and the stack trace
   * (which could be `null` if the stream itself received an error without
   * stack trace).
   * Otherwise it is called with just the error object.
   * If [onError] is omitted, any errors on the stream are considered unhandled,
   * and will be passed to the current [Zone]'s error handler.
   * By default unhandled async errors are treated
   * as if they were uncaught top-level errors.
   *
   * If this stream closes and sends a done event, the [onDone] handler is
   * called. If [onDone] is `null`, nothing happens.
   *
   * If [cancelOnError] is true, the subscription is automatically canceled
   * when the first error event is delivered. The default is `false`.
    */
  StreamSubscription<T> listen(void onData(T event),
      {Function onError, void onDone(), bool cancelOnError});

This means you can do more than simply pass one handler for emitted data, you can also have a handler in case of errors and if the Stream is closed from the side of the Stream controller (onDone). Exceptions that get thrown from inside the Stream will call onError() if you provide it, otherwise they’re just swallowed and you’ll never know that something went wrong.

Flutter Stream Example

To make it easier for you to follow the next chapters, I made a separate branch in the repository.
Please clone/switch to this branch https://github.com/escamoteur/stream_rx_tutorial/tree/counter_stream

For the first example I took the well known counter App that you get when you create a new Flutter Project and refactored it a bit. I added a model class to hold the state of the App, which is basically just the counter’s value:

class Model
{
    int _counter = 0;
    StreamController _streamController = new StreamController<int>();

    Stream<int> get counterUpdates => _streamController.stream;

    void incrementCounter()
    {
        _counter++;
        _streamController.add(_counter);
    }
}

here you can see a very typical pattern: Instead of publishing the whole StreamController, we just publish its Stream property.

In order to make the Model accessible by the UI, I made it a static field in the App object because I didn’t want to introduce an InheritedWidget or a ServiceLocator. We can get away with this for a simple example but I wouldn’t want to do it with a real App!

In main.dart we add:

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  StreamSubscription streamSubscription;

  @override
  void initState() {
    streamSubscription = MyApp.model.counterUpdates.listen((newVal) => setState(() {
          _counter = newVal;
        }));

    super.initState();
  }

  // Although this state will not get destroyed as long as the App is running its good
  // style to always free subscriptions
  @override
  void dispose() {
      streamSubscription?.cancel();
      super.dispose();
    }

InitState() is a good place to set up the ‘trap’, and being good Dart citizens we always make sure to free the subscription in dispose(), right?

In the widget tree we just need to adapt the onPressed handler of the FAB (Floating Action Button).

    floatingActionButton: new FloatingActionButton(
            onPressed: MyApp.model.incrementCounter,
    tooltip: 'Increment',
    child: new Icon(Icons.add),
    ),

By doing this, we’ve created a clean separation between View and Model, using a Stream.

Using a StreamBuilder

Source: https://github.com/escamoteur/stream_rx_tutorial/tree/streambuilder

Instead of using initState() and setState() for our needs, Flutter comes with a handy Widget called StreamBuilder. As you may have guessed, it takes a Stream and a builder function, calling it whenever a new value is emitted by the Stream. We don’t need initState or dispose for that:

body: new Center(
  child: new Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
      new Text(
        'You have pushed the button this many times:',
      ),
      StreamBuilder<int>(
          initialData: 0,
          stream: MyApp.model.counterUpdates,
          builder: (context, snappShot) {
            String valueAsString = 'NoData';

            if (snappShot != null && snappShot.hasData) {
              valueAsString = snappShot.data.toString();
            }

            return Text(
              valueAsString,
              style: Theme.of(context).textTheme.display1,
            );
          }),
    ],
  ),
),

We’re almost at the end, I promise. Here are three things that are good to know:

  • In the above layout, one big advantage of using StreamBuilder compared to the first solution is that calling setState() in listen() will always rebuild the full page, while StreamBuilder will only call its builder.

  • The snapShot variable contains the most recent data that was received from the Stream. Always check to ensure it contains valid data before using it.

  • Because of the sequence things are initialized in during build(), the StreamBuilder cannot receive a value during the very first frame. To get around this, we pass a value for initialData that gets used for the first build, meaning the first frame, of the screen. If we don’t pass initialData our builder function will get called with an invalid snapShot on the first frame. An alternative to using initialData is to return a ‘place holder widget’ if `snapShot is invalid that is displayed until we receive valid data like:

// Let's assume our stream does not emit items based on a button but on some update in a database
StreamBuilder<int>(
    stream: MyApp.model.databaseUpdates,
    builder: (context, snappShot) {

    if (snappShot != null && snappShot.hasData) {
        return Text(
          snappShot.data.toString(),
          style: Theme.of(context).textTheme.display1,
        );
    }

    // Until we receive a valid data we display a waiting Spinner
    return CircularProgressIndicator ();
  }),

In the next post we’ll take a look at how to transform the data on our Streams and do it on the fly. But please be patient, I won’t be back from vacation till the end of August. Many thanks to Scott Stoll for proof reading and important feedback.

It is really important to me that you understand Streams. If you didn’t understand something in this post or think it could be better explained please let me know so that I can improve it.

RxVMS a practical architecture for Flutter Apps

This is the fist post of a series of posts that will explain my take on App architecture for Flutter. It will be highly opinionated so be warned 😇

Planned posts so far:

  • Introduction (this post)
  • Fundamentals of Dart Streams
  • RxDart: Magical transformations of Streams
  • RxVMS foundations: RxCommand and GetIt
  • RxVMS: Services & Managers
  • RxVMS: The self responsible widget
  • User Authentication the RxVMS way

Background

I’m in software now for about 20 years. I started with mobile 4 years ago with Xamarin Forms because cross platform was the only thing that made sense to me for an Indie App. Xamarin Forms almost forces you to use MVVM because you define the UI in XAML so you need some glue layer to connect the UI to your Model seems to make a lot of sense on the first view. While working with Xamarin I was introduced to ReactiveUI and fell in love with streams and Reactive Extensions (Rx) which made my Apps much more robust.

While using MVVM with Xamarin Forms was just natural I was surprised when coming to Flutter that there was no recommend architectural pattern. So I started to explore different options but didn’t really like any of them:

  • InheritedWidget never managed to make it only update the part of the Widget tree that’s data changed, so I just used it to access a model class publishing Dart Streams but soon dropped it in favour of a generic Service Locator
  • Scoped Model better than InheritedWidget but didn’t give me the flexibility I was used from ReactiveUI
  • Redux which was the one pattern that was recommend from a lot developers coming from React Native. I have written a whole post on why I don’t like it
  • BLOC If I hadn’t already started to work on my own pattern when BLOC was promoted I probably would have be stuck with it because it offers a really flexible and reactive solution. What I don’t like is that it publishes Stream Sinks so I can not just pass a function/command to an event handler of a Widget. Also having one big BLOC object doesn’t make live easier if you develop in bigger team and makes testing harder.
  • MVVM As I was used to it I first checked out if it would fit with Flutter too. It doesn’t! The whole point of an ViewModel is to provide representation of your model to that it can be easily consumed by your Views by using Bindings. But Flutter doesn’t update its Widgets with new data, it always rebuilds them as I discussed here. Further ViewModels need to keep in sync with the underlying Model which can lead to nasty bugs and reality shows that the promised advantage of reuse ViewModels across Apps almost never happen. Adam Pedley has a great ranting post on the shortcomings

The ugly truth of too much Layering

It’s almost a dogma in software development that you always should build your Apps in several layers where each layer should only access the next layer below because it will allow you to:

  • Reuse layers in other project
  • Let’s you easily replace on layer with another one
  • Makes them easier testable

I have almost no project I have seen that whole layers got reused. If you have generic code that can be used somewhere else it makes much more sense to factor that out into a generic library. Also replacing whole layers is not a really common use case. Most people will never replace a data base after an App is beyond a certain development stage, so why add an abstraction layer for it. And in case you really have to our current development tools make refactoring quite easy. What it makes indeed easier is testing.

I don’t say you shouldn’t use layering but I question if we have to do it as strictly as we did in the past. Extensive layering lets you use a lot of code and can make problems in keeping a single source of truth of your App’s state. Introduce layers only where it helps you not just because it’s a best practice.

An ideal architecture for Flutter

So what do I expect from an ideal architecture?

  • Make it easy to understand how your App works. This one extremely important goal for me. New developers starting with an existing App’s code should be able to follow execution paths easily
  • Make it easy to work as a team on one App
  • The architecture itself should be easy to understand and to follow
  • No boiler plate code just to make the architecture work
  • Support the reactive UI approach of Flutter
  • Make debugging easy
  • Don’t hurt Flutters great performance
  • Easy to extend
  • Make testing easy
  • Let’s you focus on your Application instead of internals

The self responsible Widget

Given the aimed stateless nature of Flutter UIs one Page/Widget shouldn’t depend on another Page/Widget or change another Page/Widget. This lead to the idea that every Page/Widget should be self responsible for displaying itself and all it’s user interactions. This will make it easy to understand how your App works as you typically explore an App beginning from its UI. It also would make it easy to split work between developers because one developer can work on one Page without the need to know of the work of others.

RxVMS

RxVMS is an evolution of RxVAMS that I described in a previous post While applying RxVAMS in my current real world Flutter project I realized some weaknesses in it and improved it.

The current result of all this thoughts is what I call RxVMS which stands for Rx-View-Managers-Services. It fulfils all the above goals with the only requirement that you have to grasp Streams and parts of Rx. To help you with that I will devote the next post.

This is a partial schema of my current App

RxVMS

Services

These are abstractions of interfaces to the outside of your App this can be a Database which requires you to serialize your objects, a REST API or some hardware of your phone. They don’t change any state of your app.

Managers

Managers group together semantically related functionality. Like everything needed for user management / authentication, everything related to an order or to your product catalogue. They provide CRUD operations on your objects.

Every state change (change of data of your App) has to be done through a Manager. They typically don’t store state themselves unless it’s critical for performance or it’s data that doesn’t change throughout the live time of the App.
They also can provide data sources for views if the data needs some additional transformation after retrieving it from a service. An example could be if you need to access two different data sources and combine them to one business object that a View can display. Managers can interact with each other.

Views

Typically a StatefullWidget or a Widget that contains a StreamBuilder so that it can consume returned data from Managers or Services. This will often be a whole Page but could also be a complex custom Widget. They do not store any state that has to persist. Views are allowed to directly access Services so far they don’t change any state.

Domain Objects

Although not in the diagram this are the objects that represent your business objects. In other models they belong to their own Model layer which also contains all business logic. In RxVMS they don’t contain any business logic that could change state. They are almost always plain data objects. (If I had included them it would have got RxVMMS which is long and VM could be misunderstood as ViewModel). Logically they belong to the manager layer.

In the upcoming posts we will explore this parts and how they work together in detail.

One to find them all: How to use Service Locators with Flutter

Most people when starting with Flutter will start looking for a way how to access their data from the views to separate them. What’s recommended in the Flutter docs is using an InheritedWidget which not only allows to access data from anywhere in the Widget tree but also should be able to automatically update widgets that reference it.

Some problems with InheritedWidgets

Any descendant of InheritedWidget should be immutable which means you cannot change its data but have to create a new instance with new data. To be able to do this inside the widget tree you always have to wrap it in a StatefulWidget.

If an InheritedWidget changes not only the Widgets that reference it will be updated, because not the Widgets but the next surrounding context get registered. Which means that at least this full context including all its children will be rebuilt. Meaning if you place your inherited Widget at the very base of your tree it will rebuild the whole tree.

When reading the docs you get the impression that it shouldn’t be that way but neither I nor other developers I know have managed it that only referencing widgets get rebuilt.

So you would have to add different InheritedWidgets at different places inside your tree to minimize the rebuilt.

If someone can show me how it’s done the right way so that it works like expected I would me happy

When accessing an `Inherited by writing:

MyInheritedWidget.of(context).myProperty

Flutter will look into the next outer context and check if its registered in there. If not it will walk up the tree and check in the outer contexts too, meaning depending how deep you are in the tree this can take some time.

Alternatives

Given that the automatic updating of referencing widgets seems not to be optimal implemented we might ask why should I use an InheritedWidget at all.
Especially if you are using the InheritedWidget only to access your model from anywhere e.g. when using the BLOCK or other reactive patterns there are other solutions that might even be better.

Singletons

Might be the very first thing that springs to mind. While a Singleton greatly solves the job of making it easy to access an object from anywhere it makes unit testing very difficult because you only can create one instance of it and its hard to mock.

IoC containers with Dependency Injection

While this is a possible alternative to solve accessing a certain object while keeping it flexible to test I have some objection against automagical injection of objects at runtime.

  • At least for me it makes it more difficult to follow where a certain object instance is coming from. But that’s a matter of taste I guess
  • Using an IoC container creates a network of dependent object which has the result that when you access the first object inside this network all dependent objects will be instantiated at the same moment which can hurt performance at start-up time especially for mobile apps. Even objects that might only be needed at a later time might be created without need. (I know that there are IoCs that offer lazy creation but that doesn’t completely solve this problem)
  • IoC containers typically need some sort of reflection to figure out which objects have to be injected where. As Dart doesn’t support in Flutter this can only be solved using code generation tools.

Service Locators

Like with IoCs you have to register types that you want to access later. The difference is that instead of letting an IoC inject instances automatically you call the service locator explicit to give you the desired object.

I know there are many people that have objections against this pattern calling it old fashioned and hard to test although the later one isn’t really true as we will see. IMHO it’s far more important to get software out of the door instead spending a lot of time with theoretical discussions which is the best possible pattern. For me and many others Service Locators are just a straight forward practical pattern

One nice side effect of using an Service Locator or IoC is that you are not limited to use it inside a widget tree but you can use it anywhere to access any type of registered objects.

GetIt a Service Locator for Dart

Coming from C# I was used to use a very simple Service Locator (SL) called Splat. So I tried if I could write something similar in Dart too with the result of GetIt.

GetIt is super fast because it uses just a Map<Type> inside which makes accesses to it O(1).

Globals strike back or the Return of the Globals

One big difference to C# is that Dart allows the use of global variables. Which means I didn’t need to implement GetIt as singleton or static class to access it from anywhere in the App.

I almost can here some of you shudder when reading the word ‘global variable’ especially if you are an old timer like me who was always told globals are bad. Not long ago I learned a much nicer term for them: ‘Ambient variables’ which might sound a bit like a hyphenism but actually describes the intention much better. These are variables that keep objects instances that define the ambience in which this app runs.

Usage

It’s pretty straight forward. Typically at the start of your app you register the types that you want later access from anywhere in your app. After that you can access instances of the registered types by calling the SL again.

The nice thing is you can register an interface or abstract class together with a concrete implementation. When accessing the instance you always ask for the interface/abstract class type. This makes it easy to switch the implementation by just switching the concrete type at registration time.

Getting practical

I refactored a very simple example to use GetIt instead of an inherited Widget. To initialize the SL I added a new file service_locator.dart which also contains the global (ambient) variable for the SL. That makes it also easier to reference it when writing unit tests.

// ambient variable to access the service locator
GetIt sl = new GetIt();

 void setup() {
      sl.registerSingleton<AppModel>(new AppModel());
}

GetIt has different methods to register types. registerSingleton ensures that you always get the same instance of the registered object.

Using the InheritedWidget the definition of a button looked like:

new MaterialButton(
        child: new Text("Update"),
        onPressed: TheViewModel.of(context).update
        ),

Now with GetIt it changes to

new MaterialButton(
        child: new Text("Update"),
        onPressed: sl.get<AppModel>().update
        ),

Actually because GetIt is a callable class we can write

new MaterialButton(
        child: new Text("Update"),
        onPressed: sl<AppModel>().update
        ),

Which is pretty concise.

you can find the whole code for the SL version of this App here https://github.com/escamoteur/flutter_weather_demo/tree/using_service_loactor

Extremely important if you use GetIt: ALWAYS use the same style to import your project files either as relative paths OR as package which I recommend. DON’T mix them because currently Dart treats types imported in different ways as two different types although both reference the same file.

Registration in Detail

Different ways of registration

Besides the above used registerSingleton there are two more ways to register types in GetIt

Factory

sl.registerFactory<AppModel>( () => new AppModelImplementation()) )

If you register your type like this, each call to sl.get<AppModel>() will create a new instance of AppModelImplementation given that it’s an descendent of AppModel. For this you have to pass a factory function to registerFactory

LazySingleton

As creating the instance on registration can be time consuming at app start-up you can shift the creation to the time the object is the first time requested with:

sl.registerLazySingleton<AppModel>(() => new AppModelImplementation())

Only the first time you call get<AppModel>() the passed factory function will be called.

Applications beyond just accessing models from views

When using an SL together with interfaces/abstract classes (I really wished Dart would still have interfaces) you get extremely flexible in configuring your apps behaviour at runtime:

  • Easy switching between different implementations of services E.g. define your REST API service class as abstract class “WebAPI” and register it in the SL with different implementations like different API providers or a mock class:
// Important to register services that might be used in AppModel constructor first
sl.registerSingleton<WeatherAPI>(new WeatherAPIEmulation() );
//sl.registerSingleton<WeatherAPI>(new WeatherAPIOpenWeatherMap() );
sl.registerSingleton<AppModel>(new AppModel());
  • Register parts of your widget tree in the SL and register different implementations at runtime depending on the screen size (phone/tablet)

Overriding registrations

You are not limited to register any type at start-up. You can do it also later.
If necessary you even can override an existing registration.
By default you will get an assertion if you try to register a type that is already registered because most of the time this might not your intention. But if you need to do it you can by setting GetIt’s property allowReassignment=true.

Testing with GetIt

Testing with GetIt is very easy because you can easily register a mock object instead the real one and then run your tests.

Get it offers a reset() method that clears all registered types so that you can start with a clean slate in each test.

If you prefer to inject you mocks for the test this pattern for objects that use the SL is recommended:

AppModel([WeatherAPI weatherAPI = null]): 
  _weatherAPI  = weatherAPI ?? sl<WeatherAPI>(); 

Flutter: Bindings? What bindings?

Bindings: Typically used in frameworks that declare the UI in a mark-up language like Xaml that automagically updates widgets and properties in linked ViewModels.

Having worked with Xamarin Forms for 3 years I understand the confusion some get when starting with Flutter. The most disturbing questions you get are

  • Where is my BindingContext
  • How do I make Bindings

The terrible truth is:

There are no Bindings in Flutter

That’s because of the way Flutter Pages are created. As Flutter always rebuilds its widgets on data changes there is no way we can define a static binding between a Widget and a property in a ViewModel. You have to do all data exchange manually.
This sounds like a lot of work, but on the upside it’s very straight forward and you have full control over it. Thinking on how often I had problems to debug binding problems it’s actually sort of relief.

How to access the ViewModel/AppModel

As Flutter widgets don’t have a BindingContext we need another way to access our ViewModel. The easiest way would be just to use a Singleton for this but Flutter has a special Widget for this called InheritedWidget which can be accessed from anywhere of its children. Therefore if we place an InheritedWidget at the very root of our widget tree we can access it from any other Widget during the build process.

This is the InheritedWidget that we will use in our demo App (in model_provider.dart):

// InheritedWidgets allow you to propagate values down the Widget Tree.
// it can then be accessed by just writing  ModelProvider.of(context)
class ModelProvider extends InheritedWidget {
  final AppModel model;

  const ModelProvider({Key key, @required this.model, @required Widget child})
      : assert(model != null),
        assert(child != null),
        super(key: key, child: child);

  static AppModel of(BuildContext context) =>
      (context.inheritFromWidgetOfExactType(ModelProvider) as ModelProvider)
          .model;

  @override
  bool updateShouldNotify(ModelProvider oldWidget) => model != oldWidget.model;
}

It will wrap our ViewModel/AppModel and with the handy static of method we can access it by calling

ModelProvider.of(context)

To make it accessible we put it at the base of our widget tree:

class TheApp extends StatelessWidget {

  final AppModel model;

  const TheApp({Key key, this.model}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return new ModelProvider(
      model: model,
      child: new MaterialApp(
        title: 'Binding Demo',
        home: new MainPage(),
      ),
    );
  }
}

One way binding

Which means we only update the view with data from the App/ViewModel but not vice versa.
For this demo we use a very simple AppModel:


class AppModel { String singleFieldValue = "Just a single Field"; }

To display this field we only have to reference the the ModelProvider in our MainPage‘s build method (main_page.dart):

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Binding Demo")),
      body: 
      Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          children: <Widget>
          [
       -->   Text(ModelProvider.of(context).singleFieldValue),

One nice side effect of that we assign a value on every rebuild is that we can also call any method at this place so for instance to make the value capitalized for displaying:

  Text( ModelProvider.of(context).singleFieldValue.toUpperCase() );

So no need for special converters.

Two way binding

Let’s assume we want a TextField to enter a text that should be initialized with a value and update the ViewModel if its value changes:

Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: Text("Binding Demo")),
    body: 
    Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        children: <Widget>
        [
          Text("Single Text field:"),
     -->  TextField(
             controller: TextEditingController(text: ModelProvider.of(context).singleFieldValue,),
     -->     onChanged: ( newValue) => ModelProvider.of(context).singleFieldValue = newValue,
          ),

To initialize a TextField we have to use the TextEditingController of the Widget. To save changes back to our AppModel we have to assign a method to the onChanged handler of the widget which is best done using a lambda method.

Getting dynamic

In this step we will generate several TextFields dynamically from a collection of the AppModel. For that we extend the AppModel:

class FormEntry {
  String title;
  String content;

  FormEntry(this.title,this.content);
}

class AppModel {
    List<FormEntry> formEntries = new List<FormEntry>();

    String singleFieldValue = "Just a single Field";

    AppModel()
    {
      // Fill the List with initial values
      formEntries.addAll(
        [
          FormEntry("Name:","Burkhart"),
          FormEntry("First Name:","Thomas"),
          FormEntry("email:","[email protected]"),
          FormEntry("Country:","Wakanda"),
        ]);
        printContent();
    }

    void printContent()
    {
       print("Single TextField: $singleFieldValue");
       print("\n");

       formEntries.forEach((entry)=> print("Field: ${entry.title} - Content: ${entry.content}"));
       print(" ");
    }
}

and the build method like that:

Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: Text("Binding Demo")),
    body: 
    Padding(
      padding: const EdgeInsets.all(8.0),
      // creating a column with the single value field and a list of Textfields
      child: Column(
        children: <Widget>
        [
          Text("Single Text field:"),
          TextField(
              controller: TextEditingController(
            text: ModelProvider.of(context).singleFieldValue.toUpperCase(),
          ),

          onChanged: ( newValue) => ModelProvider.of(context).singleFieldValue = newValue,
          ),

          Padding(
            padding: const EdgeInsets.only(top: 50.0, bottom: 10.0),
            child: Container(
              color: Colors.blue,
              height: 3.0,
            ),
          ),

          Text("Multiple Fields:"),

          Expanded(child: 
            ListView.builder(
                itemCount: ModelProvider.of(context).formEntries.length,
                // This builder function is called "formEntries.length" times.
                itemBuilder: (context, index) {
                  return Padding(
                    padding: const EdgeInsets.only(top: 8.0),
                    child: 
                    Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>
                      [
                        Text(
                          ModelProvider.of(context).formEntries[index].title,
                          style: TextStyle(fontSize: 20.0),
                        ),
                        TextField(
                          controller: TextEditingController(
                              text: ModelProvider.of(context).formEntries[index].content),
                          // because a new lambda function is created for 
                          // each item, it can capture the current value of index 
                          onChanged: (newValue) => 
                            ModelProvider.of(context).formEntries[index].content = newValue ,
                        )
                      ],
                    ),
                  );
              }),
          ),
          // Will print the current value of the `formEntries`collection in the AppModel
          MaterialButton(
            child: Text("Print"),
            onPressed: ModelProvider.of(context).printContent,
          )
        ],
      ),
    ),
  );

Let’s have a closer look at the creation of the TextField:

TextField(
  controller: TextEditingController(text: ModelProvider.of(context).formEntries[index].content),
  onChanged: (newValue) => 
    ModelProvider.of(context).formEntries[index].content = newValue ,
)

The ListView.builder will generate a ListView by calling a provided builder function with the index of the current item. Because we use a lambda function it can capture the passed index through Darts closure feature so that the correct index is used when the handler is called.

You can find the code for this step here: https://github.com/escamoteur/two_way_binding/tree/direct_access

Doing some clean-up

Directly writing to fields in the AppModel is not really a good idea so we add this two methods to the AppModel

updateSingleValueField(String value ) => singleFieldValue = value; 

updateFormEntry(int index, String value) {
  print("Updated Field index: $index: $value");
  return formEntries[index].content = value;
}

You may have already realized if you have run the App in the previous state that when tapping one of the TextField that they are not pushed into view when the keyboard pops up. Because of a current bug this doesn’t happen automatically so we have to do a little workaround which consists of theses steps:

  • wrapping the bodyof the Scaffold into a SingleChildScrollView to enable the body to scroll
  • Because ScrollViews don’t work without problems with a ListView in it Simon Lightfoot contributed some helper classes:
// Generates a Column dynamically from a a builder method 
class ColumnBuilder extends StatelessWidget {
    final IndexedWidgetBuilder itemBuilder;
    final MainAxisAlignment mainAxisAlignment;
    final MainAxisSize mainAxisSize;
    final CrossAxisAlignment crossAxisAlignment;
    final TextDirection textDirection;
    final VerticalDirection verticalDirection;
    final int itemCount;

    const ColumnBuilder({
        Key key,
        @required this.itemBuilder,
        @required this.itemCount,
        this.mainAxisAlignment: MainAxisAlignment.start,
        this.mainAxisSize: MainAxisSize.max,
        this.crossAxisAlignment: CrossAxisAlignment.center,
        this.textDirection,
        this.verticalDirection: VerticalDirection.down,
    }) : super(key: key);

    @override
    Widget build(BuildContext context) {
        return Column(
            children: new List.generate(this.itemCount,
                    (index) => this.itemBuilder(context, index)).toList(),
        );
    }
}

Which is a nice example of the extensibility of Flutter. The building function now looks like that:

body: new SingleChildScrollView(
        child: Padding(
    padding: const EdgeInsets.all(8.0),
    child: Column(
      children: <Widget>[
        Text("Single Text field:"),
        TextField(
            controller: TextEditingController(
              text: ModelProvider.of(context).singleFieldValue,
            ),
            onChanged: ModelProvider.of(context).updateSingleValueField),
        Padding(
          padding: const EdgeInsets.only(top: 50.0, bottom: 10.0),
          child: Container(
            color: Colors.blue,
            height: 3.0,
          ),
        ),
        Text("Multiple Fields:"),
        ColumnBuilder(
            itemCount: ModelProvider.of(context).formEntries.length,
            itemBuilder: (context, index) {
              return Padding(
                padding: const EdgeInsets.only(top: 8.0),
                child:   
                 EnsureVisible( duration: Duration(milliseconds: 200),
                          ensureVisibleBuilder: (context, focusNode) =>
                    Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text(
                          ModelProvider.of(context).formEntries[index].title,
                          style: TextStyle(fontSize: 20.0),
                        ),

                        TextField(focusNode: focusNode,
                          controller: TextEditingController(text: ModelProvider.of(context).formEntries[index].content),
                          // because a new lambda function is created for each item, it can
                          // capture the current value of index
                          onChanged: (newValue) =>
                               ModelProvider.of(context).updateFormEntry(index, newValue),
                        )
                      ],
                ),)
              );
            }),
        MaterialButton(
          child: Text("Print"),
          onPressed: ModelProvider.of(context).printContent,
        )
      ],

EnsureVisible is another helper widget that ensures that its child is scrolled into view as soon as it gets the focus. As this will hopefully be fixed soon by the framework I won’t go into details on this.

You can find the code for this step here: https://github.com/escamoteur/two_way_binding/tree/using_functions

If you ran the App and edited one of the fields you may have realized in the debug view that AppModel.updateFormEntry is called after each character that is entered. Often that isn’t what we really want. Especially on a page with multiple TextFields it is desired that the data is only updated if all fields are validated and saved together, so that the user can cancel this operation easily, which btw. is an advantage to automatic two way bindings.

Using Forms

This scenario is solved by the Form widget. A Form combines one or more FormFields together so that they can be validated and saved all together.

You can find more on forms validation here

To access the Form from our Button we have to use a GlobalKey because its not in the same tree branch as the Form otherwise we could look it up with context.ancestorWidgetOfExactType.

To access the keys easily we put them into a class as static fields (app_keys.dart):

class AppKeys {
  static final GlobalKey form = new GlobalKey();
}

With a Form it now looks like this:

Text("Multiple Fields:"),

new Form(key: AppKeys.form,
      child: 
      ColumnBuilder(
          itemCount: ModelProvider.of(context).formEntries.length,
          itemBuilder: (context, index) 
          {
              return Padding(
                padding: const EdgeInsets.only(top: 8.0),
                child:    
                EnsureVisible(duration: Duration(milliseconds: 200), ensureVisibleBuilder: (context, focusNode) =>
                  Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>
                    [
                      Text(ModelProvider.of(context).formEntries[index].title,
                            style: TextStyle(fontSize: 20.0),
                            ),

                      TextFormField(
                          focusNode: focusNode,
                          controller: TextEditingController(text: ModelProvider.of(context).formEntries[index].content),
                          // because a new lambda function is created for 
                          // each item, it can capture the current value of index
                          onSaved: (newValue) => 
                              ModelProvider.of(context).updateFormEntry(index, newValue),
                    ],
                  ),
                )
              );
            }),
),
MaterialButton(
  child: Text("Print"),
  onPressed: () 
        { 
            FormState state = AppKeys.form.currentState;
            state.save();
            ModelProvider.of(context).printContent();
        }
)

You will have realized that a TextFormField has a slightly different constructor:

TextFormField(ontroller: new TextEditingController(text: ModelProvider.of(context).formEntries[index].content),
    focusNode: focusNode,
    onSaved: (newValue) => ModelProvider.of(context).updateFormEntry(index, newValue),
    )

The event handler is now called onSave which means it will be called if the parent FormState's save method is called.
This is a bit counterintuitive that we have to access the FormState and not the Form itself but because the Form doesn’t keep any state it’s not able to hold the save logic.

Luckily if you assign any widget a GlobalKey you can access the widget, the widget’s state if it’s a StatefullWidget and the widget’s context over the GlobalKey like on the button:

MaterialButton(
  child: Text("Print"),
  onPressed: () 
        { 
            FormState state = AppKeys.form.currentState;
            state.save();
            ModelProvider.of(context).printContent();
        }
)

You can find the code for this step here: https://github.com/escamoteur/two_way_binding/tree/using_form_fields

Updating widgets

So far we only transferred values from the AppModel to the page on the first build of the page. If we change any values inside our AppModel this won’t be reflected in the view because it won’t trigger any rebuild, which is actually a good thing compared to automatic bindings that would trigger updates on any data change. The downside is we have to manually trigger the rebuild of our screen. To show this I add a second button that will change the value of our ViewModel. There are several ways we can trigger an update:

The call-back approach

One way to deal with that is that we change our MainPage from a StatelessWidgetto a StatefulWidget so that we can register a call back in the states didChangeDependencies method:

class MainPage extends StatefulWidget {

  @override
  MainPageState createState() {
    return new MainPageState();
  }
}

class MainPageState extends State<MainPage> {

  @override
  void didChangeDependencies() {
      ModelProvider.of(context).addListener(() => setState((){}));
      super.didChangeDependencies();
    }

  @override
  Widget build(BuildContext context) {
    return Scaffold(

We cannot register the call-back in initState because the context isn’t available at that time.

To make this work we inherit the AppModel now from ChangeNotifier which allows to register listeners and raise notifications to that listeners.

Calling the setState in the call-back will trigger a full rebuild of the States child.

I also added a print output that will show if the whole Page was rebuild:

Column(children: <Widget>
[
  Text(() {print("************** Was updated****"); return "Single Text field:";}()  ),

Using a lambda like this is a handy way to debug the build process of the widget tree

If you start this version of the App and hit Update you will see this message as second time after start-up which means we have updated the whole page although we just change the content of our list of FormFields.

You can find the code for this step here: https://github.com/escamoteur/two_way_binding/tree/update_with_call_back

The stream approach

If you have read my blog post on reactive Flutter you know that I’m a big friend of Streams and StreamBuilders which rebuild their children as soon as they receive a new item from a Stream. So this is a very elegant approach to make your View update when your data changes.

To make that work we add a StreamController to the AppModel which will create a Stream to which we can push events:

class AppModel {
    List<FormEntry> formEntries = new List<FormEntry>();
    StreamController<List<FormEntry>> listUpdates = new StreamController<List<FormEntry>>(); 

    ....

    changeAppModel()
    {
      formEntries.clear();
      formEntries.addAll(
        [
          FormEntry("Name:","New Name"),
          FormEntry("First Name:","New First Name"),
          FormEntry("email:","New email"),
          FormEntry("Country:","New Country"),
        ]);

  -->   listUpdates.add(formEntries); // This will trigger the update
    }

And in the MainPage:

Text("Multiple Fields:"),

new Form(key: AppKeys.form,
      child: 
      new StreamBuilder<List<FormEntry>>(
            stream: ModelProvider.of(context).listUpdates.stream,
            initialData: ModelProvider.of(context).formEntries,
            builder: (context, snapShot)
            {
              List<FormEntry> list = snapShot.data;
              return ColumnBuilder(
                    itemCount: ModelProvider.of(context).formEntries.length,
                    itemBuilder: (context, index) 
                    {
                        return Padding(
                          padding: const EdgeInsets.only(top: 8.0),
                          child:    
                          EnsureVisible(duration: Duration(milliseconds: 200), ensureVisibleBuilder: (context, focusNode) =>
                            Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: <Widget>
                              [
                                Text(list[index].title,
                                    style: TextStyle(fontSize: 20.0),
                                    ),

                                TextFormField(controller: new TextEditingController(text:list[index].content),
                                    focusNode: focusNode,
                                    // because a new lambda function is created for each item, 
                                    // it can capture the current value of index
                                    onSaved: (newValue) => ModelProvider.of(context).updateFormEntry(index, newValue),
                                    )
                              ],
                            ),
                          )
                        );

If you run this App you will see that only the Widgets below the StreamBuilder are updated.

You can find the code for this step here: https://github.com/escamoteur/two_way_binding/tree/using_stream

Redux, the ideal Flutter pattern?

When starting with Flutter I was looking for recommendations for App architecture and most of the time I found references to the Redux pattern.
I’m really honest, Redux never appealed to me. I understand the idea behind the unidirectional data flow but it just seemed too much overhead.

But I wanted to take it to a test and try to create App that is identical to one created with Redux but with the RxVAMS pattern (which I proposed in my last blog post) .

When Iiro Krankka open sourced his beautiful App inKino which is build using redux I had my candidate.

inKino

I asked Iiro if it would be ok if I take his App and refactor it to RxVAMS and he is looking forward to the outcome.

Trying to find out how an Redux app works turned out to be more difficult than expected. Normally when inspecting source code of an app someone else wrote I start with the UI trying to follow the program flow that is triggered by an user action. Trying to do that by using the IDE’s “Go to definition” and “Find all references” didn’t really help because of the way Redux decouples classes. I can only agree with Paul Betts on this:

paulbettsonredux

Comparing the project structure

folder-structure-reduxfolder-structure-rx

The Redux version needs 24 classes for its state management where the Rx version only uses one: app_model.dart


Raw numbers

I wrote a small analysis tool DartStatistics to count code lines, characters and number of classes:

Version Code Lines Code characters classes
Redux 3109 74561 75
RxVAMS 2412 56137 44

This means Redux needs about 30% more lines and characters of code than RxVAMS to achieve the same functionality.

But what if the App gets more complex?

As this App only has one real Page with user interaction I use only one class the AppModel to hold all state of the App. If the App would consists of more complex pages the AppModel would provide a PageModel for each of this Pages that would relay data to the AppModel or directly to the service layer.

The Redux version stores all app state inside one store class so not so much difference here but it needs a lot more code to access and modify it.

But, but Redux will prevent a lot of errors!

True, the fact that views cannot modify state directly but only over dispatching actions might beware you of potential errors but for the price that your code gets much harder to understand and you have to create much more code to reach that goal.
More code also means more places to make mistakes.

Using Streams and RxCommands to communicate between model and view you get an easier to understandable architecture that works without side effects too and you always can follow your code using your IDE’s search commands.

Readability before everything else

If you ever came back to one of your own project after a year you know the feeling to have the feeling someone else must have written this code. Same for any developer that gets the task of continuing the development of a project because the original creator has left the company. So easy to understand and to follow code is paramount.

Why do we use complex patterns?

  • Reusability of code: I really would like to know how many of you have really reused bigger parts of an App in completely different one that wouldn’t be better placed in a independent library from the begin.
  • Exchangeability of components: Often be introduce additional abstraction layers. But who of you have really changed the database after an app was finished?
  • Extensibility: I think it was Kent Beck the creator of Extreme Programming how made the point that using modern IDEs it’s pretty easy to make big refactorings even in large code bases. Having automated tests implemented make sure that you don’t accidentally break something.
  • Error prevention: State management is one of the most difficult areas of any App so using patterns that preventing side effects are a good idea. If one pattern will save you at the end of the day will only show time. Choose a pattern that doesn’t compromise understandability of your code.
  • Testability: This is actual the one that has shown its benefits in daily use. But even here I always will prefer manual Dependency injection before automagically working IOC containers.

I don’t say that these goals are not important and may be helpful from time to time but I want to encourage you to question existing development trends and hypes. Trying to strive for simplicity is a good goal overall.

Try it on your own

O.K. you got it, I don’t like Redux 🙂 You don’t have to believe me so give it a try yourself. Clone both repositories and try to understand how the apps work and share your experiences with us in the comments. I’m really curious to hear them.

Here are the repositories:

Redux inKino

RxVAMS inKinoRx

I’m still exploring how to refine the use of RxCommands with Flutter and there are still some points where I’m not completely satisfied but I will continue this exploration and hope some of you will join me.

Making Flutter more Reactive

When chatting with some dev about the reactivity of Flutter he made the great statement Flutter is REACTive and not reactive in the sense we know from Reactive Extensions (Rx).

Coming from Xamarin and ReactiveUI this somewhat disappointed me because if you once started to think the Rx way you never want to go back.

From MVVM to RxVAMS

Coming from Xamarin Forms MVVM is the natural architectural pattern for Apps for me. MVVM solves a lot of problems while still is easy to understand and don’t introduce unnecessary components.

Please stay with me for a moment we come back to Flutter I promise

I won’t describe MVVM in detail this is excellently done here

MVVM

It basically consists of three layers where the View which consists of all UI elements you see on the screen. It can also contain logic that only concerns the UI. The Model contains your business logic and backend connections. The ViewModel is the glue between both in that it processes and transforms data from the Model to a form the View can easily display. It offers functions (often called Commands) the View can call to trigger actions on the Model and provides events to signal the View about data changes.

Important: The ViewModel knows nothing about the View which makes it testable and more than one View can use the same ViewModel. A ViewModel just offers services to the View (events, commands). The _View decides which it uses.

Several MVVM frameworks encapsulate the subscription of events and calling functions to update data in the ViewModel from the View using DataBindings

To trigger any other action in the View besides data updates from the ViewModel gets tedious because you have to publish events and functions if the View should be able to retrieve data as a result of the event.

Another problem is that we always moving state between the different layers which have to be kept in sync.

What we really want is an App that just reacts on any event from the outside without having to deal with state management all the time.

Rx to the rescue

If you never heard of Rx before think of it as streams of events on that you can do transformations in a Linq like manor. Although Rx was first developed be Microsoft it is no available to almost any Language. You can find an introduction on reativex.io From there:

The ReactiveX Observable model allows you to treat streams of asynchronous events with the same sort of simple, combindable operations that you use for collections of data items like arrays. It frees you from tangled webs of call-backs, and thereby makes your code more readable and less prone to bugs.

When working with Rx you define rules how to react on events in a declarative way. This is done in a functional manor to reduce any side effects. Applied to MVVM this means all communication between layers happen over even streams (called Observable in Rx) and reactive commands. Best of all Observable streams are asynchronous by nature.

The Dart implementation of Rx is RxDart.

ghuntley

Introducing RxVAMS

I have no idea if anybody else will use this name but I like it 🙂

There is another observation that leaves some doubt if MVVM is the right pattern for mobile Apps. MVVM was aimed at sharing the code of Model and even ViewModel between different apps which is really rarely the case.
Looking at real world apps you often realize that the model layer degenerated to a service layer that connects the app to the rest of the world and that the VieModels have more and more logic in it instead just beeing an adapter. The reason for this is that typical apps don’t deal with complex business logic. So I propose the following pattern for Apps:

RxVAMS

This also separates the App in three layers but replaces the ViewModel with an AppModel that contains the whole app logic and the interface for the View consisting of reactive commands (in the following RxCommands) and Observables that offer state changes to the view.
In order to react on events the View subscribes to this Observables

The Model is replaced by a designated Service layer which offers all services that connects the app to the outside (REST APIs, device APIs, databases). Data from the Service Layer is returned as Observable or be asynchronous function calls to make the access asynchronous.

If you don’t want to follow this pattern just replace AppModel with ViewModel in your mind for the rest of the post.

Calling to action

I made a little demo app to show the following in practise. It queries a REST API for Weather data and displays it in a ListView. I made branches for every step of the rest of this post so that you can easily try it yourself.

A big, big thank to Brian Egan for polishing the App for the last step, even including unit and UI Tests!

Inject the AppModel to the View

Code for this step

To access an object from anywhere in the widget tree Flutter offers the concept of the InheritedWidget. When added to a widget tree the InheritedWidget can be accessed anywhere down that tree by calling its static of() method.

In main.dart:

class TheViewModel extends InheritedWidget
{
  final HomePageAppModel theModel;

  const TheViewModel({Key key, 
                      @required 
                      this.theModel, 
                      @required 
                      Widget child}) :  assert(theModel != null),assert(child != null),
                      super(key: key, child: child);

  static HomePageAppModel of(BuildContext context) => (context.inheritFromWidgetOfExactType(TheViewModel)as TheViewModel).theModel;                  

  @override
  bool updateShouldNotify(TheViewModel oldWidget) => theModel != oldWidget.theModel;

}

In this case the .of() doesn’t return the inherited widget but directly the contained HomePageAppModel instance as it is the only data field.

As we want to have our AppModel available anywhere in our HomePage we insert it in the very top of our widget tree.

In main.dart:

class MyApp extends StatelessWidget {
  // This widget is the root of your application.

  @override
  Widget build(BuildContext context) {
    return new TheViewModel( 
                  theModel:  new HomePageAppModel(),
                  child: 
                  new MaterialApp(
                    title: 'Flutter Demo',
                    home: new HomePage()
                  ),
                );
  }
}

Step 1: Making the Views Reactive

Code for this step

The typical way to react with Flutter on events from a ViewModel is to create a StatefulWidget and subscribe to an event in the initState method of the State and call setState on each event.

Using StreamBuilder and Streams instead of event subscriptions is the first step to make this easier StreamBuilder takes a stream as an input and calls its builder function each time it receives a new input:

In listview.dart:

Widget build(BuildContext context) {
    return new StreamBuilder<List<WeatherEntry>>(   // Streambuilder rebuilds its subtree on every item the stream issues
            stream: TheViewModel.of(context).newWeatherEvents,   //We access our AppwModel through the inherited Widget
            builder: (BuildContext context, AsyncSnapshot<List<WeatherEntry>> snapshot)  // in Dart Lambdas with body don't use =>
                {
                // only if we get data
                if (snapshot.hasData && snapshot.data.length > 0)
                {
                    return new ListView.builder(
                                itemCount: snapshot.data.length,
                                itemBuilder : (BuildContext context, int index) => 
                                                    buildRow(context,index,snapshot.data)                                            
                    );
                }
                else
                {
                    return new Text("No items");
                }
            }                                              
            );                            

Anytime someone queues a new Lists of WeatherEntry in this stream this ListView will be recreated with the latest data.

This happens in homepage_appmodel.dart:

// Subjects are like StreamSinks. You can queue new events that are then published on the .observable property of th subject. 
final _newWeatherSubject = new BehaviorSubject<List<WeatherEntry>>() ;

// Only the observable of the Subject gets published
Observable<List<WeatherEntry>> get newWeatherEvents  => _newWeatherSubject.observable;

update({String filtertext = ""})
{
     _newWeatherSubject
        .addStream( WeatherService.getWeatherEntriesForCity(filtertext)
                                        .handleError((error)=> print)       // if there is an error while accessing the REST API we just make a debug output
                    );          
}

Querying data and updating are completely decoupled which makes testability easy.

update is triggered by pressing the update button on the page

In homepage.dart:

new MaterialButton(                               
        child: 
        new Text("Update"), // Watch the Button is again a composition
        color: new Color.fromARGB(255, 33, 150, 243),
        textColor: new Color.fromARGB(255, 255, 255, 255),
see->   onPressed: TheViewModel.of(context).update
        ),

and if the user types into the filter TextField.

In homepage_appmodel.dart:

_inputSubject.observable
.debounce( new Duration(milliseconds: 500))  // make sure we start processing if the user make a short pause 
    .listen( (filterText)
    {
    update( filtertext: filterText);
    });  

Will call execute if a new string was queued into HomePageAppModel._inputSubject which happens in this method:

// Callback function that will be registered to the TextFields OnChanged Event
onFilerEntryChanged(String s) => _inputSubject.add(s); 

Again the event and the reaction are decoupled through a Subject and and Observable which allows further event processing like the debounce operator which makes sure that only an event is emitted if there wasn’t another change within a given period.

So to make your views reactive Streambuilder is the key. So far almost everything besides the debounce could be done too by using Dart Streams instead of Observables.

Step 2 adding RxCommands

To enable the Views to call functions in a reactive way I wrote the RxCommand package which is heavily inspired by the ReactiveCommand class of the .net framework ReactiveUI. To be more correct this enables AppModels to react “reactive” on function calls from the View.

RxCommand takes a function when created through one of its static factory methods. This method can be called by using its execute method or by directly calling the RxCommand object because it’s a callable class. This makes it possible to assign a command directly to an event of a Widget.

Nothing special so far but any result of wrapped function is emitted from the RxCommand over its results property which is you might already expect it an Observable. Especially when wrapping an async function with an RxCommand the .exceute will return immediately but the result will be emitted when the function returns.

Besides moving to RxCommands this iteration adds a busy spinner and a Switchto disable the update functionality. The App now looks like this:

App_Step_2

In homepage_model.dart:

class HomePageAppModel {

RxCommand<String,List<WeatherEntry>>  updateWeatherCommand;
RxCommand<bool,bool>  switchChangedCommand;
RxCommand<String,String>  textChangedCommand;

HomePageAppModel()
{
    // Command expects a bool value when executed and issues the value on its result Observable (stream)
    switchChangedCommand = RxCommand.createSync3<bool,bool>((b)=>b);

    // We pass the result of switchChangedCommand as canExecute Observable to the upDateWeatherCommand
    updateWeatherCommand = RxCommand.createAsync3<String,List<WeatherEntry>>(update,switchChangedCommand.results);

    // Will be called on every change of the searchfield
    textChangedCommand = RxCommand.createSync3((s) => s);

    // handler for results
    textChangedCommand.results
        .debounce( new Duration(milliseconds: 500))  // make sure we start processing only if the user make a short pause typing 
        .listen( (filterText)
        {
            updateWeatherCommand.execute( filterText); // I could omit he execute because RxCommand is a callable class but here it 
                                                        //  makes the intention clearer
        });  

    // Update data on startup
    updateWeatherCommand.execute();
}

No more Subjects and handler functions just clean RxCommands. Let’s look at it step by step beginning with the textChanged command. The function that it wraps doesn’t do anything else than pushing the passed string out of the RxCommand.result Observable, to which the handler below listens.

In other Rx implementations listen is called subscribe. As RxDart is based on Dart’s `Streams’ listen is used.

The switchChangedCommand too just pushes the received bool to its result observable. It will be assigned to the onChanged handler of the Switch widget and issue a new bool value every time the Switch changes its state. This may seem a bit pointless because nobody seems to care about this results.

But looking at the updateWeatherCommand we see that switchChangedCommand.results is passed as a second (optional) parameter. That’s the next feature of RxCommand you can pass am Observable<bool> which determines if the command can be executed or not. In our case this will make the updateWeatherCommand react to any change of the Switch automatically.

On the View’s side the commands are directly used as handler functions which is possible because they are callable classes:

In ‘homepage.dart’

new TextField(
        autocorrect: false,
        decoration: new InputDecoration(
                            hintText: "Filter cities",
                            hintStyle: new TextStyle(color: new Color.fromARGB(150, 0, 0, 0)),
                            ),
        style: new TextStyle(
                    fontSize: 20.0,
                    color: new Color.fromARGB(255, 0, 0, 0)),
-->     onChanged: TheViewModel.of(context).textChangedCommand,),

Special Features:

Not only does RxCommand offer a .results Observable but also this Observables:

  • .isExecuting emits a bool value every time the execution state of the command changes. So after calling execute it will emit true and when the wrapped function returns (even an async one) it will emit a false.
  • .canExecute emits a bool value every time the executability of the command changes. This will emit false while the command is executing but will also reflect the status of the canExecute observable if one was passed to the when creating the command. This allows to effectively set up rules on executability of multiple commands.
  • .thrownExceptions if there is a listener on this observable RxCommand will catch any exception that are thrown by the wrapped function and emit them here.
  • RxCommands can not be called again while they are executing. If you want to disable command A while another command B is executing you only have to pass B.isExecuting when creating A as canExecute parameter. Cool isn’t it? 🙂

Let’s make use of this features in the App. For instance it’s very easy to add a busy Spinner now by using another StreamBuilder that listens on updateWeatherCommand.isExecuting:

From homepage.dart:

new StreamBuilder<bool>(   
    stream: TheViewModel.of(context).updateWeatherCommand.isExecuting, 
    builder: (BuildContext context, AsyncSnapshot<bool> isRunning)  
        {
            // if true we show a buys Spinner otherwise the ListView
        if (isRunning.hasData && isRunning.data == true)
        {
            return new Center(child: new Container(width: 50.0, height:50.0, child: new CircularProgressIndicator())); 
        }
        else
        {
            return new WeatherListView();                                  
        }
    })                                              
    ),

Code for this step

While Brian did some refactoring on the example app he made the point that it would be helpful to have all three states (isExecuting, results, error) in one stream because Flutter updates its UI by rebuilding it. Using separate StreamBuilder might not always be ideal.

I totally agree with him. With frameworks that use bindings and update only single controls through them the separate streams were a good solution. For flutter I want to display alternative Widgets depending on the new state at one place during rebuild. This lead to the introduction of the CommandResult<T> class:

/// Combined execution state of an `RxCommand`
/// Will be issued for any statechange of any of the fields
/// During normal command execution you will get this items if directly listening at the command.
/// 1. If the command was just newly created you will get `null, false, false` (data, error, isExecuting)
/// 2. When calling execute: `null, false, true`
/// 3. When exceution finishes: `the result, false, false`

class CommandResult<T>
{
  final T         data;
  final Exception error;
  final bool      isExecuting;

  const CommandResult(this.data, this.error, this.isExecuting);

  bool get hasData => data != null;
  bool get hasError => error != null;

  @override
  bool operator == (Object other) => other is CommandResult<T> && other.data == data &&
                         other.error == error &&
                         other.isExecuting ==isExecuting;  
  @override
    int get hashCode => hash3(data.hashCode,error.hashCode,isExecuting.hashCode);
}

To get notified of any new CommandResult you can directly .listen to the command itself because RxCommand now also implements the Observable interface.

In the next step we will use that to our advantage.

Making life easier with rx_widgets

Using StreamBuilder is one way to react to AppModel events but it makes the Widget tree a bit messy and because I’m also lazy I wrote the rx_widgets package which contain convenience function to work with Streams, Observables and RxCommands.

You can pass an Observable at any place a Stream can be used because Observables extends the Stream interface

Currently it contains this classes:

RxSpinner a platform aware busy spinner that takes a Stream and builds a running Spinner on trueand on false and alternative Widget.

With this the code from above would look like:

new RxSpinner(busyEvents: TheViewModel.of(context).updateWeatherCommand.isExecuting,
                platform: TargetPlatform.android,
                radius: 20.0,
                normal: new WeatherListView(),) 

As we want to take care of errors and empty data events too now there is also an extended version that takes directly an RxCommand and offers three builders:

RxLoader<List<WeatherEntry>>(
        spinnerKey: AppKeys.loadingSpinner,
        radius: 25.0,
        commandResults: ModelProvider.of(context).updateWeatherCommand,
        dataBuilder: (context, data) => WeatherListView(data ,key: AppKeys.weatherList),
        placeHolderBuilder: (context) => Center(key: AppKeys.loaderPlaceHolder, child: Text("No Data")),
        errorBuilder: (context, ex) => Center(key: AppKeys.loaderError, child: Text("Error: ${ex.toString()}")),
        ),

WidgetSelector builds one of two provided Widgets depending on the bool value the provided Stream emits. In our app I use it to enable/disable the update Buttton based on the updateWeatherCommand.canExecute Observable.

In homepage.dart:

new Expanded(
    child: 
    WidgetSelector(
        buildEvents: ModelProvider.of(context).updateWeatherCommand.canExecute,   //We access our ViewModel through the inherited Widget
        onTrue:  RaisedButton(    
                        key: AppKeys.updateButtonEnabled,                           
                        child: Text("Update"), 
                        onPressed: ()  
                            {
                                _controller.clear();
                                ModelProvider.of(context).updateWeatherCommand();
                            }
                    ),
        onFalse:  RaisedButton(                               
                        key: AppKeys.updateButtonDisabled,                           
                        child: Text("Please Wait"), 
                        onPressed: null,
                        ),
    ),
),

More reactive widget goodies to come soon. If you have an idea for a great RxWidget just open an issue or even better make a PR.

Conclusion

Thanks to Brian Egan our App now looks like this:

App_Step_3

By using Streamsor even better RxDart’s Observables in combination with StreamBuilder and RxCommands and rx_widgets can make your App truly reactive.

If you got hooked on the idea of streams of events, vote for this Flutter issue to make Flutter use Dart Streams for notifications.

Flutter – The new kid on the block

In this post I will have a closer look at Google’s new mobile framework Flutter and compare it to my previous experience with Xamarin forms. This is not a tutorial but more an overview to get you started

A typical day with Xamarin

As most of you know I really like Xamarin Forms. After a break of halve a year I got back to mobile. First thing was updating Visual Studio with Xamarin. When trying to build my App which built fine the last time I was working on it I got a whole bunch of errors. After 3 hours fiddling with the toolchain I was able to build again.
Pretty frustrated because I had hoped that things had improved with Xamarin in the meantime I read that Google just announced the official beta release of its new cross platform mobile framework Flutter. So I decided to have a closer look at it.

What is Flutter

Flutter is not only a framework, it’s actually a whole tool chain for building native Apps for Android and iOS.

  • Flutter promises real write once run everywhere including the UI
  • Flutter doesn’t use any OS UI controls but paints everything with Skia
  • Flutter provides Widgets that exactly mimic the look of Material and iOS Controls
  • Flutter‘s core is written in C++ so it’s really fast
  • You write Flutter programs using the language Dart which is AOT compiled into native code
  • It offers an instant reload function so that you can see any change you make to the App in moments on your device/emulator while the app’s state is preserved
  • You program your UI not in some mark-up language like XAML but completely in code which sounds more cumbersome than it is as we will see.

Taking it to a test

Installation

Following the instruction on the Flutter.io page installation on Windows is pretty straight forward. I only had a complain about some Android SDK licences which could be fixed by creating a blank App in latest Android studio. Additionally I installed Dart Code the Dart and Flutter plugin for VS Studio Code.

If you install on Mac it can be a bit more work, so had I to upgrade to Mac OX High Sierra and also to update several tools which was ok because the Flutter installer tells you what is missing and how to install.

It just works

Opening the first sample and hit F5 in VS code and the app was build deployed and started without any problems. I was really surprised because I was no longer used to something like that.

One thing I should mention: when building for iOS you have to work on your Mac, you cannot remote build like with Xamarin

Let’s write our own first Flutter program

I decided to port a small App that I did before in Xamarin forms. You can find the code here:

Into the Dar(k)t ages

Coming from C# I was surprised how easy it is to get accustomed with Dart the syntax is not so much different and on the Dart website you find all you need. I will point out interesting features of Dart when we get to code.

A Flutter Project

FlutterProjectStructure

This is a typical project structure of a Dart project. All your source files including main.dartare located in the lib folder. For now the only other interesting file is the pubspec.yaml where you register all packages that your project needs as well as all assets. Be careful, yaml files are very picky when you don’t follow the correct indentation.

Widgets all around

Our goal is an UI like this:

mainscreen

Flutter builds it’s UI completely through composition of Widgets that can again contain Widgets.
Yes, in Flutter everything is a Widget, even the App itself. As already mentioned the UI is completely build in code but compared with building a Page in Xamarin Forms this is very straight forward and with a little practice as good readable as a Xaml page.

Every widget has a build method that is responsible to create it’s own subtree of widgets:

class HomePage extends StatelessWidget
 {
  @override
  Widget build(BuildContext context) {
      return 
         new Scaffold(  // A material control with an Appbar and a body
            appBar: new AppBar(title: new Text("WeatherDemo")),
            body: 
              new Column(children: <Widget>
              [
               new Padding(padding: const EdgeInsets.all(5.0),child: 
                      new TextField(
                              autocorrect: false,
                              decoration: new InputDecoration(
                                                  hintText: "Filter cities",
                                                  hintStyle: new TextStyle(color: new Color.fromARGB(150, 0, 0, 0)),
                                                  ),
                              style: new TextStyle(
                                            fontSize: 20.0,
                                            color: new Color.fromARGB(255, 0, 0, 0)),
                              onChanged: TheViewModel.of(context).OnFilerEntryChanged,),
                ),//Padding

                new Expanded( child: 
                      new WeatherListView(),  // Have to wrap the ListView into an Expanded otherwise the Column throws an exception
                    ),//Expanded

                new Padding(padding: const EdgeInsets.all(8.0),child: 
                      new MaterialButton(                               
                              child: 
                                new Text("Update"), // Watch the Button is again a composition
                              color: new Color.fromARGB(255, 33, 150, 243),
                              textColor: new Color.fromARGB(255, 255, 255, 255),
                              onPressed: TheViewModel.of(context).update
                              ),
                ), // Padding

              ],
            ),//Column
          );//Scaffold
  }

So our page is basically made of a Scaffold container with a Column which contains three “rows”: A TextField, a ListView and a Button. The ListView was moved to its own Class so that the structure keeps readable.

As you see this is pretty straight forward. Decomposition in custom classes or just in a function is faster done than creating a custom view in Xamarin Forms.
Another advantage in using code to create your UI is that you can use code to dynamically create elements.

With Dart 2 it won’t even be necessary to use new because the compiler will infer it automatically so that UI code looks nicer.

You may have wonder what this TheViewModel.of(context).update is. That’s Flutter‘s way of providing a DataContext to the Widgets. For this you have to create an InheritedWidget that’s only function is to propagate data down the widget tree from where it is placed in the tree. In this App I placed one at the very root of the tree so that all Widgets have access to my ViewModel.

Flutter Widgets are in principle stateless which means you cannot store any data in it as they will completely (not completely true) new created when refreshing the screen. One consequence is that we don’t have permanent bindings between View and ViewModel that update automatically.

When I wrote in principle stateless this was not completely true. Besides the StatelessWidget above there are StatefullWidgets too that are made of a Widget and a State object. This State object is persistent during rebuilds of the UI and can so store information and subscribe to event handlers of view models.

Building the ListView

 WeatherListView();
    @override
    Widget build(BuildContext context) {
      return new StreamBuilder<List<WeatherEntry>>(   // Streambuilder rebuilds its subtree on every item the stream issues
              stream: TheViewModel.of(context).newWeatherEvents,   //We access our ViewModel through the inherited Widget
              builder: (BuildContext context, AsyncSnapshot<List<WeatherEntry>> snapshot)  // in Dart Lambdas with body don't use =>
                  {
                    // only if we get data
                    if (snapshot.hasData && snapshot.data.length > 0)
                    {
                        return new ListView.builder(
                                    itemCount: snapshot.data.length,
                                    itemBuilder : (BuildContext context, int index) => 
                                                      buildRow(context,index,snapshot.data)                                            
                                );//ListView
                    }
                    else
                    {
                      return new Text("No items");
                    }
                } // Builder function                                              
              );//Streambuilder

    }            

StreamBuilder is a nice Widget which will execute a builder method that rebuilds its widget subtree each time a new item is issued by a given Stream which allows a reactive design of your app. There is even a Dart version of Reactive Extensions that builds on top of Dart Streams.

This means every time the ViewModel pushes new data into the other side of the Stream the ListView will be recreated.

All collection widgets in Flutter exist in two versions. One that takes a predefined List of Items and a builder version that calls a handler every time it needs the data for a new row it wants to display which allows easy data virtualisation.

Moving the creation of the individual Rows into a separate function makes it again more maintainable:

Widget buildRow(BuildContext context, int index, List<WeatherEntry> listData) {
    return 
    new GestureDetector(
        child: 
            new Wrap(spacing: 40.0,
                children: <Widget>
                [
                    new Image(image: new NetworkImage(listData[index].iconURL)),

                    new Text(listData[index].cityName, style: new TextStyle(fontSize: 20.0))
                ],
                ),

        onTap: () => Navigator.push(context, 
                        new MaterialPageRoute( builder: (BuildContext context) => new DetailPage(listData[index])
                ))
    );

I hope this gives you a very first impression how UIs are build in Flutter

Conclusion

Having worked now for three weeks with Flutter I can say

Pros

  • Reliable Tool Chain
  • Designing in Code together with the instant reload is really fun and fast. Refactoring of widgets like decomposing into smaller units is just a cut and paste in a new file. Debugging is easier too because you have no symbolic bindings.
  • Exactly same look of your App on Android and iOS if you want. Soon automatic usage of platform like looking widgets will be available
  • No need for CustomRenders if you want to achieve more ambitious look and feel
  • A really huge and powerful library of Widgets that can be composed endlessly
  • Virtualized CollectionViews
  • Animations are very very easy. And they look on all platform the same.
  • Compared to a mark-up based framework the learning curve seems not as steep but this might come from my experience with Xamarin.
  • Non UI code of the app can be shared with web versions of it.
  • Fast build time
  • Very fast start-up time in release mode <2s
  • Runs as native compiled code
  • Very good API docs, examples and tutorial videos.

Cons

  • You cannot access native APIs directly from Dart. For that you have to write a plugin in either Java and Swift/Objective-C that communicates with your App through message channels
  • Currently not all device functions are available as plugins
  • The package library of Dart is nothing compared to the nuget universe
  • Currently no packages to use Azure, Firebase is there but who would have expect differently
  • Dart doesn’t support reflection which is good for performance but make a lot of tasks tedious. For instance there is nothing compared to json.net or refit luckily for JSON there is a generator library that creates serialize and deserialize code for your classes.
  • Currently there are no established application frameworks like MvvmCross or similar. Overall there are only little resources on App architecture at the moment.
  • No remote building for iOS from a PC

Overall my subjective impression is that I’m much faster in creating appealing pages than in Xamarin Forms. It feels a bit more raw the way you code but also with more control because not so much happens automagically in the background.

Currently there is a huge hype around Flutter (20.000 stars on github) and if Google really launches Fuchsia it will be the default framework there. Which lets hope that missing plugins will soon be available.
On the other side it’s still in beta and nobody know if Google may kill it before release.

My main reason for continuing with it is that I don’t get continuously frustrated by the toolchain and the fast build times.

I can only recommend give it a try and see for yourself. Especially try the Flutter Gallery sample in the Flutter repo.

More information on [fluttering] (https://flutter.io)

On Gitter: gitter.im/flutter/flutter

Let me know what else do you want to know about Flutter!

The Xamarin Project Mystery

In this post I will try to clear up some missconceptions about the Xamarin Forms project structure, have a closer look at the differences between PCL and Shared Projects and explain some tricks that you can do with both of them.

First there was confusion

I recall when I started with Xamarin the wizard created solution looked pretty alien to me. At this time I started with a PCL based solution because that’s what was recommended everywhere. We’ll have closer look ate this later in this post

pcl_project_structure

There was a (portable) subproject and one with .Android and one with .iOS extension. After reading some docs I understood that the PCL part is a platform independent library and in the other two are the platform specific code. Still I did not understand how are these projects connected to each other. I got further confused reading that I cannot call any platform specific code from the PCL project unless I use the Xamarin Dependency Service

This left the feeling that there must be some black magic going on under the hood that brings all together which left me a bit uncomfortable but it seemed to work somehow.

No Magic in here

The most confusing part was that all my Apps important code like the App class and all my pages were in the PCL project. So I thought that’s the project that will generate the final App and that the other two just get linked somehow.

What I did learn while already happy coding was that the .Android and .iOS projects are the so called Platform Projects which will result in our final App when compiled and linked. This projects will just link in the PCL part which just a dll, that’s all to it. So in reality it was exaclty the oposite that I first thought.

PCL_project_schema

This has some interesting consequences. Although code in the PCL cannot access code inside the platform projects the other way round is indeed possible.

This suddenly also explained how the DependencyService could work. It’s code is located in the Xamarin Forms (XF) library which is a PCL itself and which is referenced from our PCL project and from the Platform Project which makes it possible for the Platform Project to register instances of platform dependent classes inside the XF code which then can be retrieved via it’s platform independent interface from inside our PCL project.

We don’t need magical attributes and Services

to access platform specific code. All it takes is a static property in a class in our PCL project and a platform independent interface like

public interface IFileStorage
{       
    string ReadAsString(string filename);
    byte[] ReadAsBytes(string filename);
}

In each of the Platform projects we implement this interface with a platform specific implementation.

Android:

namespace XamarinSampleSolutionPCL.Droid
{
    public class FileStorage : IFileStorage
    {
        public string ReadAsString(string filename)
        {
            var bytes = ReadAsBytes(filename);
            return Encoding.UTF8.GetString(bytes);
        }

        public byte[] ReadAsBytes(string filename)
        {
            AssetManager assets = Android.App.Application.Context.Assets;
            using (Stream stream = assets.Open(filename))
            {
                using (var memStream = new MemoryStream())
                {
                    stream.CopyTo(memStream);
                    return memStream.ToArray();
                }
            }
        }

    }
}

iOS

namespace XamarinSampleSolutionPCL.iOS
{
    public class FileStorage : IFileStorage
    {
        public byte[] ReadAsBytes(string filename)
        {
            var data = File.ReadAllBytes(filename);

            return data;
        }

        public string ReadAsString(string filename)
        {
            var data = ReadAsBytes(filename);

            if (data == null)
                return string.Empty;

            return System.Text.Encoding.UTF8.GetString(data);
        }

    }
}

In our App class in the PCL Project I added a static property:

namespace XamarinSampleSolutionPCL
{
    public partial class App : Application
    {
        public static IFileStorage FileStorage;

To make everything working together we have to create an instance of the platform specific classes and assign it to this static property and we can use it inside the PCL over this static property.

Here is the example how to do it in Android:

protected override void OnCreate(Bundle bundle)
{
    TabLayoutResource = Resource.Layout.Tabbar;
    ToolbarResource = Resource.Layout.Toolbar;

    base.OnCreate(bundle);

    global::Xamarin.Forms.Forms.Init(this, bundle);

>>  App.FileStorage = new FileStorage(); // Thats the interesting line

    LoadApplication(new App());
}

I don’t say that this is an optimal solution! But it should give you a better understanding of how this projects play together. Using a ServiceLocator like the XF DependencyService has the advantage that your PCL code does not use a static property of any of your classes and you can access the instance from anywhere in your code. If you want to use a ServiceLocator I personally prefer Splat which gives you much better control and does work without magical class attributes.

What are these other files for?

This might seem trivial for some of you but from my experiences in the Xamarin Slack not everyone knows. Stay tuned we will get more interesting stuff in a minute.

  • package.config: nuget packages that you add to your project are stored in here. But don’t think you can just edit it to add or remove packets because they are also referenced in your .csproj files. So always use the nuget Manager or the console

In the PCL

  • App.xaml and App.xaml.cs: if you have read my previous post (if not do it now) you know that the combination of .xaml and .xaml.cs just creates a class. In this case your Appclass which has the responsibility to create your first page in it’s constructor. Although it has a .xaml part this is not a page. In the .xaml part you can define global styles and the like. If I don’t need the xaml part I often replace this combination with a simple App.cs class like
public class App : Application
{
    public static IFileStorage FileStorage;

    public App()
    {
        InitializeComponent();

        MainPage = new XamarinSampleSolutionPCL.MainPage();
    }

    protected override void OnStart()
    {
        // Handle when your app starts
    }

    protected override void OnSleep()
    {
        // Handle when your app sleeps
    }

    protected override void OnResume()
    {
        // Handle when your app resumes
    }
}

In the Android project:

  • MainActivity.cs: OnCreateis the first method that is called when your App starts up. So all platform specific initialization should go there.

In the iOS project:

  • AppDelegate.cs: here FinishedLaunchingis the first Method to get called when our App starts up.

Shared Projects, the black sheep of the family

If you ask in the community which one of the two you should choose you almost for certainly will hear Shared Projects are bad which actually almost got to some sort of dogma.

But first what are Shared Projects anyway? So lets have a look what the structure of a shared project looks like:

shared_project_structure

Looks pretty similar but what’s that strange symbol:

shared_part_symbol

This is actually a pseudo project which means it’s not a real project at all but a trick of Visual Studio (That’s the reason why you cannot add a nuget to it).

All files that you add to this “project” will be added to all platform projects at the same time by using file links.

shared_project_shema

I left out the link step intentionally

So if all files get compiled to the same binary this means that all files could access platform specific code. But to be able to compile the files in the shared part in both platform projects they should not do that because what knows an iOS compiler about Android APIs.

The idea is that you only put classes in the shared part that don’t use any platform specific code.

But (and here comes the critique of the people that think shared projects are bad) you can use #if __ANDROID__ and #if __IOS__ in the shared part to still use platform dependent code which makes a mess of your code and is bad style.

That you can do this does not means you have to or you should do and doesn’t make Shared Projects bad. Although it somehow comforts me to know that I have this possibility as last resort 🙂 .

As long as you follow this rule there is really nothing bad about Shared Projects and fact is the core App code will seldom reused in another project.

Put all code you want to reuse somewhere else in a separate PCL project and reference that from the Platform Projects and you are fine.

Advantages of Shared Projects

If you ever used a PCL project you will earlier or later have encountered the moment where a nuget that you want to use does not match the PCL profile of your PCL project which is pretty annoying especially because you cannot change your PCL profile without uninstalling all nugets first. Even worse as more and mode nugets are migrated to netstandardthe successor to PCL you will get more conflicts.

A shared project can consume any nuget independent from it’s PCL profile. So for now I actually recommend Shared Projects if you start a new one. This might change when netstandard tooling gets more mature and with the release of netstandard 2.0.

Accessing Platform code from the shared part of Shared Project

As we should not use #if what else can we do. Actually you have two possibilities.

  1. You still can use a ServiceLocator like Splat and register your platform specific interface implementations in the Platform project classes and access them via the interface and the Locator in the Shared part.

  2. You can use partial classes what someone called the poor man’s bait and switch. This makes especially sense if the class contains platform independent and dependent code.

Let’s implement the same service as in the PCL Solution in the Shared project:

In the Shared Part we add a file named FileStorage.cs

    public partial class FileStorage
    {

        // This is a stupid example for a platform independent method
        string ReadUpperString(string filename)
        {
            return ReadAsString(filename).ToUpper();
        }

        string ReadAsString(string filename)
        {
            return ReadAsStringImplementation(filename);
        }

        byte[] ReadAsBytes(string filename)
        {
            return ReadAsBytesImplementation(filename);
        }

    }

In the Android Part we add a file named FileStorage.Android.cs

Please note that we cannot use the same file name

public partial class FileStorage 
{
    public string ReadAsStringImplementation(string filename)
    {
        var bytes = ReadAsBytes(filename);
        return Encoding.UTF8.GetString(bytes);
    }

    public byte[] ReadAsBytesImplementation(string filename)
    {
        AssetManager assets = Android.App.Application.Context.Assets;
        using (Stream stream = assets.Open(filename))
        {
            using (var memStream = new MemoryStream())
            {
                stream.CopyTo(memStream);
                return memStream.ToArray();
            }
        }
    }

}

This part can fully access the Android APIs

And in iOS:

public partial class FileStorage
{
    public byte[] ReadAsBytesImplementation(string filename)
    {
        var data = File.ReadAllBytes(filename);

        return data;
    }

    public string ReadAsStringImplementation(string filename)
    {
        var data = ReadAsBytes(filename);

        if (data == null)
            return string.Empty;

        return System.Text.Encoding.UTF8.GetString(data);
    }

Our Solution now looks like this:

shared_project_structure_partial_class

You can find both solutions on my Github Repository:

PCL Solution

Shared Solution

The secret life of a Xaml Page

Disclaimer: Post describes Xaml Pages used in Xamarin Forms

If you are like me the first time when confronted with a Xaml page they look sort of really alien to an old school programmer who has never did dirty web stuff before.
After reading some articles about using them you finally grasp what you can do with them but still there is a sort of magic around them or at least if feels like a strange sort of animal that you have learned how to ride following all the examples but still you are not really sure what it really is and how does it work and if you can trust it.

Xaml Pages are just classes

OK not completely true but at least partial (pun intended). They are one part of a page class, the other one is normally declared in your xxx.xaml.cs file. Visual Studio only knows that they belong together and displays them linked together so that they look like some special thing.

If you have a Xaml Page like

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="FormsTest.Pages.BasicPage">
  <Label Text="Hello Forms" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

with it’s counterpart

using Xamarin.Forms;

namespace FormsTest.Pages
{
    public partial class BasicPage : ContentPage
    {
        public BasicPage()
        {
            InitializeComponent();
        }
    }
}

it is basiscally the same as if you write in code:

class BasicCodePage : ContentPage
{
    public BasicCodePage()
    {
        Content = new Label() {Text = "Hello Forms", HorizontalOptions = LayoutOptions.Center,
                                VerticalOptions = LayoutOptions.Center};
    }
}

The most important part in the Xaml header x:Class="FormsTest.Pages.BasicPage" tells the compiler to which partial c# class this Xaml belongs.

The magical part

How does this work? Basically your Xaml definitions get included in your assembly as embedded resource. When creating an instance of the page Forms parses the Xaml and instantiates the there defined classes like <Label>, <Grid>, <ScrollView> any set attributes get assigned to the same named properties of this classes.

You can see it yourself checking the objfolder of you project where you find temporary generated files of your pages like:

    public partial class BasicPage : global::Xamarin.Forms.ContentPage {

        [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "0.0.0.0")]
        private void InitializeComponent() {
            this.LoadFromXaml(typeof(BasicPage));
        }
    }

InitializeComponent();

If you look at the constructor of the partial class you find a generated call of InitializeComponent. This call instantiates and initializes all of the objects defined in the XAML file, connects them together in parent-child relationships, attaches event handlers defined in code to events set in the Xaml file, and sets the resultant tree of objects as the content of the page.
Taking this into account it now get’s clear why you NEVER EVER SHOULD TRY TO ACCESS ANY CONTROL of your page before this call because they just don’t exist at this point and you will get an exception.

Quite often you will get compiler errors that tells you that InitializeComponentdoes not exist. Looking at your partial C# class we have to admit that indeed there is no such method. So it must be defined somewhere in the from Forms generated second half of our page class. So if you get this kind of error in most cases the link between the code-behind file (how your partial class is often been called) and the Xaml definition is broken. You first stop is therefore checking the x:classdefinition in your Xaml header if the name there matches the class name of your c# class.
Another reason can be that VS or XS did not set the correct build tool for the Xaml page. Checking the Xaml files properties Custom Tool should be set to MSBuild:UpdateDesignTimeXaml and Build Action to `Embedded Resource.

Named Controls

In a lot of tutorials you see that the code is accessing the controls of the page just by there name which was set with the x:name attribute on the Xaml control.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:pages="clr-namespace:FormsTest.Pages;assembly=FormsTest"
             x:Class="FormsTest.Pages.BasicPage">

  <Label x:Name="MyLabel" Text="Hello Forms" VerticalOptions="Start" HorizontalOptions="Center" />
</ContentPage>

How does this work? The answer is that the Xamarin compiler will create a field for every named element in your Xaml definition inside your Page class. This is the code the compiler generates for the Xaml page:

    public partial class BasicPage : global::Xamarin.Forms.ContentPage {

        [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "0.0.0.0")]
        private global::Xamarin.Forms.Label MyLabel;

        [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "0.0.0.0")]
        private void InitializeComponent() {
            this.LoadFromXaml(typeof(BasicPage));
            MyLabel = this.FindByName<global::Xamarin.Forms.Label>("MyLabel");
        }
    }

If you want to dig deeper into this please check out: Anatomy_of_a_XAML_Class

Custom Controls

Recalling that

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="FormsTest.Pages.BasicPage">
  <Label Text="Hello Forms" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

The <Label> directive instantiates an Object of the class Label you could get the idea if it would be possible to use any class inside Xaml. And actually you can. Ok, not any class everywhere but you can use any from `VisualElement derived class as controls. So if you need a custom controls, you can just derive your class from an existing control and use it on your page.

E.g. if we want to have an control that capitalizes every input we could do this like so:

class CapitalEntry : Entry
{
    public CapitalEntry()
    {
        TextChanged += CapitalEntry_TextChanged;   
    }

    private void CapitalEntry_TextChanged(object sender, TextChangedEventArgs e)
    {
        Text =   e.NewTextValue.ToUpper();
    }
}

This might be a pretty naive solution but works for this example.

and use it in our Page just like this:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:pages="clr-namespace:FormsTest.Pages;assembly=FormsTest"
             x:Class="FormsTest.Pages.BasicPage">
  <StackLayout>

    <Label Text="Hello Forms" VerticalOptions="Start" HorizontalOptions="Center" />

    <pages:CapitalEntry VerticalOptions= "Start"/>

  </StackLayout>
</ContentPage>

The only thing to be able to use our own classes is to tell forms in which assembly they are to find. That’s why we need this line

 xmlns:pages="clr-namespace:FormsTest.Pages;assembly=FormsTest"

It defines Xaml namespace so that we now can reference classes from external assemblies. You only need “assembly=XXXX” if the control is in a different assembly to the page you’re referencing it from.

This also means that you can easily reuse parts of your page by defining them as separate classes and use that in your pages.
When doing this and define your “page parts” as ContentView or ViewCell derived classes you can define them in Xaml too and get even more flexibility because you can let it handle their own events in their own code-behind files to create more complex self contained custom controls.

Now I moved the content of the previous Page to a custom View class:

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:pages="clr-namespace:FormsTest.Pages;assembly=FormsTest"
             x:Class="FormsTest.Pages.PagePartView">
  <ContentView.Content>
    <StackLayout>

      <Label Text="Hello Forms" VerticalOptions="Start" HorizontalOptions="Center" />

      <pages:CapitalEntry x:Name="capitalEntry" VerticalOptions= "Start" TextChanged="Entry_OnTextChanged"/>

    </StackLayout> 
  </ContentView.Content>
</ContentView>

with it’s own code-behind file:

namespace FormsTest.Pages
{
    public partial class PagePartView : ContentView
    {
        public int MaxLength { get; set; } //Will be accessible as Xaml Attribute

        public PagePartView()
        {
            InitializeComponent();
        }

        //Limit the entry to MaxLength characters 
        private void Entry_OnTextChanged(object sender, TextChangedEventArgs e)
        {
            if (e.NewTextValue.Length > MaxLength)
                capitalEntry.Text = e.OldTextValue;
        }
    }
}

Then we can use it in our page:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:pages="clr-namespace:FormsTest.Pages;assembly=FormsTest"
             x:Class="FormsTest.Pages.BasicPage">

  <pages:PagePartView MaxLength="10"/>

</ContentPage>

As you see we can pass values to properties of our custom view as Xaml attributes.

Deriving Pages

You can derive Pages but with some limitations.

  • It’s possible to derive a Xaml Page from a Page defined in code that does not create any controls but only provides other functionality.
  • You can derive a code defined Page from a Xaml defined page that can access the Xaml defined controls of it’s parent page.
  • You cannot derive a Xaml defined Page from another Xaml defined page (unless they only define resources and no content)

If you want to derive a Xaml page from some outside defined base page the definition looks a bit strange as you have to use the base classes namespace before it is even declared:

Here an example that derives from ReactiveContentPage defines in the ReactiveUI library package.

<?xml version="1.0" encoding="utf-8" ?>
<rxui:ReactiveContentPage x:TypeArguments="pageModels:SettingsFilerPageModel" xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:rxui="clr-namespace:ReactiveUI.XamForms;assembly=ReactiveUI.XamForms"
             xmlns:pageModels="clr-namespace:FormsTest.PageModels;assembly=FormsTest"
             x:Class="FormsTest.SettingsFilterPage" BackgroundColor="Black">

This example is even more interesting because it shows that it’s possible to derive a Xaml Page from a generic base class. The generic type parameter is passed by using the x:TypeArgumentsdeclaration.

Why can’t I bind my Xaml Controls to Properties of my Page class?

A lot of developers when starting using MVVM as design principle try to bind attributes or command of their controls in the Xaml definition to properties defined in the code-behind file of the page and are surprised that this doesn’t work.

Besides that it makes no sense at all to bind to elements of your code-behind file, the reason is that the {Binding}
markup extension tries to make link between the Attribute it is set with an object assigned to the BindingContextproperty of the Page class and not to the Page itself.
Now you could get the idea and assign this.BindingContext = this inside the constructor of the page, but it really makes no sense if you recall that the compiler fuses the Xaml Definition together with the code-behind file to one single class. Binding inside one class does not make any sense at all.
If you want want access your pages controls just give them names with the x:name attribute and access them directly. And if you want to handle events in the code behind, don’t try to use commands, just use the Xaml exposed events.

Should I use the code-behind file at all?

Many MVVM purists will tell you that your code-behind files should only contain the InitializeComponentcall and nothing else.
I’m not that dogmatic. Actually if you are not using the Xamarin Forms bindings you might need to define bindings manually inside the constructor.
Second if we are talking about custom views it might not make sense to bind that to a ViewModel if it acts as a self-contained control. Think of a complex DateView that only exposes a property selected date but handles user interaction inside. This could be completly handled in the code-behind file. Another example is if you have to change some components dimensions based on the physical screen size. It makes much more sense to do this after the ‘InitializeComponent` call in the pages constructor than with a binding from the ViewModel because screen dimensions are something inherently connected to the View and not to the ViewModel.
As so often the answer is it depends 🙂

XamlCompile

You have seen before that Xaml pages are added as Resources and parsed at runtime, so many of you might have thought if this isn’t a bit slow. And indeed it is. Luckily there is a way out of it you can tell Xamarin to compile your Xaml classes directly into IL by simply setting an attribute on your class or on your whole assembly. As I don’t want to just copy the offical documentation, you can find here how to use Xaml Compilation

Advanced ListView Bindings

The traditional Binding

When first making contact with ListViews in an Xamarin Forms MVVM design you usually publish an ObservableCollection as a property of the ViewModel of your Page, bind the ItemSource of the ListView to it and then bind to the items in´the collection in your Datatemplate. Like this:

    [ImplementPropertyChanged]  //I use Fody here to not have to bother with INotifyPropertyChanged
    public class DemoListViewPageModel
    {
        public ObservableCollection<Dog> DogList

        public DemoListViewPageModel()
        {
            DogList = new ObservableCollection<Dog>();

            DogList.Add(new Dog() { Name = "Rex", Race = "German Sheppard" });
            DogList.Add(new Dog() { Name = "Barney", Race = "Poodle" });
            DogList.Add(new Dog() { Name = "Jimmy", Race = "Beagle" });
            DogList.Add(new Dog() { Name = "Rob", Race = "Labrador" });
        }
    }

    // Should be something that makes a bit of sense, so why not dogs
    [ImplementPropertyChanged]
    public class Dogs
    {
        public string Name {get; set}

        public string Race {get; set;}
    }

And in the Page then

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Examples.DemoListViewPage">
  <ContentPage.Content>
    <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="Center">
      <ListView ItemsSource="{Binding DogList}" HasUnevenRows="True">
        <ListView.ItemTemplate>
          <DataTemplate>         
            <ViewCell>
              <StackLayout HorizontalOptions="Start" >
                <Label x:Name="Name"  Text="{Binding Name}"  TextColor="Navy" FontSize="20"/>
                <Label x:Name="Race" Text="{Binding Race}"/>
              </StackLayout>
            </ViewCell>           
          </DataTemplate>
        </ListView.ItemTemplate>
      </ListView>
    </StackLayout>
  </ContentPage.Content>
</ContentPage>

That’s fine but

  • It violates MVVM in exposing the model behind it because the DataTemplate binds to model objects
  • The moment we want to store additional data for each item or execute a command from an ViewCell it get’s difficult

While the first might seem be an academic reason it really couples the model tightly to the view which makes changes in the model layer propagate to the view.

Let me elaborate on the second drawback.

  • Imagine we add a check mark (let’s asume we have such a control) to the ViewCell. Now we have to keep track of it’s state somewhere. We could bind its Toggle command to a Command in our ViewModel and also add a List<bool> checkedItems where we store the state for each item in the ListView.
  • We want to add a Add to Shopping Cart Button to our ViewCell. Again we could bind all Buttons of the ListView to a Command in our ViewModel that calls a WebService to add the item to the shopping cart. (Ok this example might be somewhat contrived)

Both both enhancements need additional code in the ViewModel to figure out which item the Command should be exceuted on which should not be the job of the ViewModel. The real reason for the problem is that our ViewModel is the ViewModel for the whole Page. The ListView is a container that holds a list of ItemViews that are defined in the DataTemplateof the ListView. So the consequence should be: Give each ItemView its own ViewModel. Which means our page’s ViewModel no longer exposes a ObservableColletion<Dogs> but ObservableColletion<DogsItemViewModel>

Introducing ViewModels for each ListView item

public class DogsItemViewModel
{
    private Dog DogObject;
    ICommand AddToCartCommand;

    public DogsItemViewModel(Dog theDog)
    {
        DogObject = theDog;
        AddToCartCommand = new Xamarin.Forms.Command(AddToCart);
    }

    public string Name => DogObject.Name;
    public string Race => DogObject.Race.ToUpper();
    public bool IsChecked { get; set; }

    void AddToCart()
    {
        WebService.Instance.AddToCart(DogObject);  // Whatever this will do ;-) 
    }
}

Now the DogsItemViewModel can handle all interaction with the ItemView on it’s own. You can even do conversions on the model data without the need to write an ValueConverter like I did with the Race property.

Now we refactor our ViewCell and make it a custom class. From it’s code behind file you can now even access it’s elements using x:Name

<?xml version="1.0" encoding="UTF-8"?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="YourNameSpace.DogItemView">


  <StackLayout HorizontalOptions="Start" >
    <CheckBox State = "{Binding IsChecked}" />
    <Label x:Name="Name"  Text="{Binding Name}"  TextColor="Navy" FontSize="20"/>
    <Label x:Name="Race" Text="{Binding Race}"/>
    <Button Text="Add to Cart" Command="{Binding AddToCartCommand}"/>
  </StackLayout>
</ViewCell>

and our Page like this:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Examples.DemoListViewPage">
  <ContentPage.Content>
    <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="Center">
      <ListView ItemsSource="{Binding DogList}" HasUnevenRows="True">
        <ListView.ItemTemplate>
          <DataTemplate>         
            <DogItemView BindingContext = "{Binding}" />
          </DataTemplate>
        </ListView.ItemTemplate>
      </ListView>
    </StackLayout>
  </ContentPage.Content>
</ContentPage>

Looks cool, doesn’t it?