slodge/MvvmCross — pull request #156 by Roosmaa (2013-02-14 15:17:12+00:00)
Title: Improved Android bindings

This turned out to be a mammoth rewrite, really sorry about that Stuart, but bear with me :)

### tl;dr

So whats new from the end-user perspective:

* View content can be set in OnCreate as with normal Android development, no need to override the OnViewModelSet method anymore
* Custom XML tags (ie <fragment />) are now possible
* Nothing is broken (at least the samples all run like they did before)

What's new when you're dealing with bindings directly:

* Data binding just works, the API mostly gets out of your way and almost no need to worry about anything
* Binding information is attached to the Android View's without requiring the data source to be present
* Binding data source can easily be changed for a [view hierarchy/tree] branch (useful for: list view, fragments [in the future], custom widgets, etc)
* Binding can be easily toggled on and off for a branch (to optimise for ViewGroups with a lot of not-bound views)
* Writing custom data bound [list view] adapters is trivial now
* Binding related extension methods were mostly replaced with ones which fit better with the new API

### The long version

As detailed in the discussion of [#54](https://github.com/slodge/MvvmCross/issues/54) the way of gathering binding information by using a custom `LayoutInflater.Factory` and enforcing usage of custom functions instead of the default `LayoutInflater` caused problems with support library code for Fragments.

The binding enhancement had to be implemented by overriding `Activity.OnCreateView`, which is used by the default `LayoutInflater` as the back up `LayoutInflater.Factory`. This enables us to get data binding without having to resort to custom APIs. (WIN)

Because we don't know what is inflating the layout nor do we know the data source, the old way of attaching bindings to the parent element didn't work.

The new binding code attaches only the binding description to the individual elements and the actual binding happens at a later stage, when the data is available or in `OnStart` at the latest.

This means we have to traverse the view's tree of children every time we rebind it. This can be somewhat of a performance hit when done in a loop, but as a single traversal it is usually negligible.

With the traversal binding and information attached to individual elements we can have two new features (which would've been very hack-ish with the old way) with almost no investment: switching out the data binding source for a branch or disabling data binding for a branch completely (before you had to use a different inflation function for that).

This data source switching enables to make list view bindings _extremely_ intuitive and simple, also it's a bit more forgiving on the Android as for every list item we don't need a FrameLayout container anymore.

AutoView code was also migrated to the new data binding code. Making the list view elements much easier to bind, adding properties for images, colours, etc will be just a matter of adding couple of lines.

The `OnViewModelSet` function was also changed from abstract into virtual method. There is no need to actually override it anymore, but if someone still does, they need to call the parent implementation (`base.OnViewModelSet()`).

I also converted *ActivityView classes into partial ones and separated the common code into a different file. Should be much easier now to deal with the copy-paste code as customisations are in a different file.

#### View binding manager

For every binding enabled Activity we create a `MvxActivityBindingManager`, which handles the life-cycle of bindings. It handles the actual binding, rebinding and unbinding of views in the hierarchy.

In the background it stores (weak) references to everything that has been bound, so that they could be easily cleaned up to prevent memory leaks.

It can also manage manually created bindings which need to be cleaned up when the activity is finishing.

#### Binding inflater

The inflation of views is intercepted by `MvxBindingInflater` which takes care of parsing the binding data and attaching the information to the newly created view. If there is no binding data it gets out of the way and lets Android create the views itself, which is a bit more future proof than before where we created everything ourselves.

#### View binding tag

We use the `MvxViewBindingTag` object to tag Android views with information regarding bindings: binding descriptions, currently active bindings, data source overrides, binding on/off toggling.

There are various extension methods to help deal with the new tag: `View.GetBindingTag`, `View.SetBindingTag`, `View.UpdateDataSource` and `View.RemoveDataSource`.

### Related issues

Issues this update will highly likely make easier to fix/complete:

* [#155](https://github.com/slodge/MvvmCross/issues/155) - VeeThree - Binadble Pager
* Fix or help with: [#17](https://github.com/slodge/MvvmCross/issues/17) - Android: MvxBindableListItemView instances leaking
* [#54](https://github.com/slodge/MvvmCross/issues/54) - Android needs fragment support now
* [#146](https://github.com/slodge/MvvmCross/issues/146) - VeeThree - Can we choose Adapter class using XML?