Finally, after a few months work, we have worked out a way to do fragment-less programming. As I discussed in previous article, fragments helps code-reusing, but in a way inter-fragments (& inter-fragment-activity) communication could be very dependent with each other.

In the coming release of Android Binding V30, which is a plugin to the base Android Binding that supports SDK version 14 and up (ICS), we have included a number of new features to achieve single view model, different views and layouts, without using the fragments, and most importantly, all layouts, view models and activity are independent.

New Markup Demo showing on Phone (800x480)

Showing on Tablet (1280x800)

Above screenshots taken from the new Markup Demo, which is already available in the market. Following discussions and code are all coming from this demo, you might get the source code from the project homepage.

The Problem

The demo interface contains of three parts.

  1. The “Category” list, which is displayed as Drop-down menu in the Action Bar.
  2. The “Demo” list, which is the left-hand-side column in Tablet view, and;
  3. The “Demo” view, which is the right-hand-side in Tablet view.

Above interfaces is too much to show in one single page, if it is in a phone view. So instead, in phone version, the above is divided into two activities, one is the category + demo lists, and after choosing the demo, it starts a new activity to show the demo itself, just like the original markup demo.

NOTE: Since not everyone have both devices (even me), I purposely set landscape and portrait in different layout, if you downloaded the demo to your device, landscape will show the tablet version and portrait will show the phone version, even your screen is large enough to show.

Design goal

  • Code reusability (of course) of the View Models.
  • Layout/View independent. At the time of binding, the View models should have no knowledge about what screen profile it is using. This part is purely up to the layout to choose.
  • We have to divide the above into a few view models, and they should not aware of the existence of other view models too.

View Models

The Launch View Model includes:

  • Categories (array list of DemoCategory class)
  • SelectedCategory
  • Demo (Current selected demo)
  • CategorySelected (command)
The Show Demo View Model includes:
  • Demo (Current showing demo)
Here is the flow for picking a demo, in tablet mode:
Categories (drop down) –select–> SelectedCategory –change–> update the demo list;
selecting something in demo list –> Change DemoLayout and DemoVm
And in phone mode:

selecting something in demo list –> Start Show Demo Activity

Layouts

main.xml (tablet version)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:binding="http://www.gueei.com/android-binding/"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<binding.BindableFrameLayout
		android:layout_width="@dimen/titles_size"
		android:layout_height="match_parent"
		binding:dataSource="SelectedCategory"
		binding:layoutId="@layout/demos"
/>
<binding.BindableFrameLayout
		android:layout_height="match_parent"
		android:layout_width="match_parent"
		binding:dataSource="Demo.DemoVm"
		binding:layoutId="Demo.DemoLayout"
/>
</LinearLayout>

main.xml (phone version)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:binding="http://www.gueei.com/android-binding/"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<binding.BindableFrameLayout
		android:layout_width="@dimen/titles_size"
		android:layout_height="match_parent"
		binding:dataSource="SelectedCategory"
		binding:layoutId="@layout/demos"
/>
</LinearLayout>

The dynamic switching portions (column) in the interface, is done by the new Bindable Layout widgets, which is included in the next release of Android Binding (i.e. you can use in Android 1.6+). So, whenever the dataSource (sub-view model) or layoutId is changed, the Bindable  Layouts will rebind the layout to view models accordingly. This make things very simple for tablet version, after selecting the demo, just change the CurrentLayout and CurrentVm, and they will be loaded on screen. Using the Bindable Layouts solved most of the problem that required the need of fragment.

But how about phone? Yes, we can add the ugly detection to see if it is in 2-column mode (as how it do in HC gallery demo), and if not, fire a new intent to a new activity. It’s not the best, right? So here is how we do, in the demos.xml (for the list of demo):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:binding="http://www.gueei.com/android-binding/"
	android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <ListView
        	android:id="@+id/demo_listview"
        	android:layout_width="match_parent"
    		android:layout_height="match_parent"
    		android:layout_weight="1"
    		android:cacheColorHint="#00000000"
    		android:choiceMode="singleChoice"
    		binding:assign="{prop=ShowDemoInNewActivity, value=FALSE()}"
    		binding:itemSource="Entries"
    		binding:itemTemplate="@layout/demos_list_item"
    		binding:checkedItemPosition="SelectedDemoPosition"
    		binding:onItemClicked="ARG(ShowDemo, =id/demo_listview.clickedItem)"
    		/>
</LinearLayout>

Nothing really too surprising in the xml, demos.xml phone and tablet version is only different in one line, binding.assign. This is a new feature which is… frankly not something related to the view itself. This provides a simple way to pass some parameter back to the View Model. We have a property in the View Model, named ShowDemoInNewActivity The meaning is obvious, as we stated in our design goal, the View Model is not layout aware. So this time, the layout TELLS the view model to fire that intent or not.

There are a number of new features available in Android-Binding V30, including (but not limited to):

  1. Binding to Action Bars
  2. Binding to sub-observable/properties (just like the above Demo.DemoVm)
  3. Action Modes binding. Supports both listviews and custom action modes
  4. Activity Binding, we treat Activity itself a big widget, you can switch the view model and layout for action bars, options menu (but not root view, but you can use bindable layouts to achieve this) on the fly.
  5. Bindable Layouts as mentioned before
  6. EventAggregator (experimental) similar to the WPF counter-part. Providing a light-weight context aware messaging channel.
  7. A few new converters

I am going to cover them in future posts. Once again, please grab the demo from the market (if you have ICS devices).

Advertisements