Showing posts with label monospace. Show all posts
Showing posts with label monospace. Show all posts

Wednesday, 13 July 2011

"M"osetta Stone II: ViewController → Activity

After my recent posts I received a question asking for tips on porting a MonoTouch app to MonoDroid. I'm going to take a crack at that over a couple of days - with the warning that you probably shouldn't rush out and buy either tool but wait for Xamarin's future Mono-on-iOS and Mono-on-Android products.

The purpose of the original "M"osetta Stone post was to give cross-platform developers a 'head start' with some high-level concepts. This post will look a little closer at a screen from the Monospace11 app: the Speakers list.


This may be a massive oversimplification, but...
if you have
___ in iOS
then you want
___ in Android
to
UIViewControllerActivitysubclass to present a screen/form/page to the user
ViewDidLoad()OnCreate()setup the UI
Add() or AddSubview()SetContentView()use in ViewDidLoad/OnCreate to 'attach' UI to display
ViewWillAppear()OnResume()load/re-load data that might change and bind to UI
UITableViewListViewvisual control that presents a scrolling list
UITableViewSourceAdaptersubclass to broker the display of a data collection to the UI
GetCell()GetView()to build the layout(UI) for each cell/row, including re-using cells/views for performance
RowSelected()ItemClick EventHandlerperform an action when a row is touched
RowsInSectionCounttell the table/list how many rows to cater for

Here's how it looks in a Visual Studio Class Diagram*
* I've greyed out some of the methods not relevant to the discussion - the iOS implementation of the alphabetic index down the right edge doesn't have an Android equivalent, for example

Notes:
  • UITableViewSource has been implemented as an nested class to resemble the iOS pattern of implementing the equivalent Obj-C protocols on the ViewController - this pattern makes no sense in Android so the classes are separate.
  • The MonoTouch example code builds the UI in C# (eg. tableView=new UITableView();AddSubview (tableView);) whereas MonoDroid loads layout XML files SetContentView(Resource.Layout.Speakers);. This can happen in both ViewDidLoad/OnCreate and GetCell/GetView where UI controls must be created and presented to the user.
  • The 'touch event handler' is in a different class: in MonoTouch the TableViewSource handles a touch for a specific row (NSIndexPath); MonoDroid implements the ItemClick EventHandler<ItemEventArgs> on the ListView for a given GetRow(e.Position).
  • Both examples use the constructor (TableViewSource/SpeakersAdapter) of the 'broker' class to pass the actual business object collection for display. This pattern lets the data be filtered/sorted/whatever before being passed in for display.
  • Calling refreshSpeakers() from ViewDidLoad/OnResume is kinda redundant in this example since the list never changes - but in other spots (eg the Favorites screen) you would want to refresh the list each time because it may have changed.

The Code
You can have a look at the MonoTouch code SpeakersViewController.cs and the MonoDroid SpeakersActivity.cs, SpeakersAdapter.cs to see the actual implementation. For MonoDroid you'll also need to check out the layout XML files Speakers.axml and SpeakersItem.axml.

One more thing...
One final piece which takes some getting used to... in MonoTouch this screen is part of a UINavigationController stack and your RowSelected creates a new ViewController object (passing whatever parameters you need) and calls NavigationController.PushViewController(). The ViewController instances in the navigation stack are 'stateful' and it is really easy to pass business objects around as parameters.
In MonoDroid, the ever-present 'back-stack' does not require a specific 'navigation controller' BUT at it's simplest the mechanism is much more primative and involves passing simple type parameters (eg. strings) like this
var intent = new Intent();
intent.SetClass(this, typeof(SpeakerActivity));
intent.PutExtra("Name", speaker.Name);
StartActivity(intent);

There are more sophisticated approaches but it is probably best to keep your parameter-passing to a minimum - this way the Android hardware 'Back' button "just works".

HTH Slava ;-)

Monday, 11 July 2011

MonoDroid v MonoTouch : a comparison

The past few days I've posted MonoDroid and MonoTouch apps for Monospace - and while they aren't perfect examples of the sort of code-sharing and efficiency that's possible with Mono I thought it would be interesting to compare them as the functionality they offer is very similar.

First, these are the high-level code metrics (as calculated by Visual Studio):
Unfortunately I didn't align the namespaces very well. Here's the explanation:

Total lines of code (TLOC)
Mono-for-Android: 802 lines
MonoTouch: 1,420 lines (2,033 - 613 in SQLite)
At first glance, the MonoDroid app 'wins' with just half the code of the MonoTouch version. I've ignored the SQLite library and the MonoTouch.Dialog framework as they aren't "user code", and any non-.cs files (eg XML markup).

Common code
Although difficult to 'see' because I've rushed these codebases into the public domain, there is a bit of 'code re-use' in these apps (ie. it was only written once, and the c# shared across both platforms using the power of Mono :)
ConfXml == MIX10Xml == approx 200 lines of business objects (DTOs mainly) that match the serialized conf.xml format that is the shared data structure for both platforms.
The ConceptDevelopment.Kelvin code is also shared (different sizes in each aren't relevant for now).

Removing the common code from the comparison results in these totals:
Mono-for-Android: 575 lines (802-199-28)
MonoTouch: 1,145 lines (1,420-178-97)

"Re-used" code
Mono-for-Android's Main.cs::DeserializeConferenceFile, LoadWhatsOn and MonoTouch's AppDelegate.cs::FinishedLaunching both contain "very similar" code in the form of the conf.xml deserializer and parser. In MonoTouch it's 70 lines and in MonoDroid it's 307 lines. The MonoTouch version is heavily assisted by the Linq/MonoTouch.Dialog code in HomeController (another 150 lines or so) which explains part of the difference... but what is shared is the deserialization logic and a number of Linq statements that help parse it for display. These would be harded to shift into a common library due to the dependency on MonoTouch.Dialog - but there was definitely an efficiency gain by having the code already written and tested on one platform before porting to the other. I'll adjust both by the same 'average' LOC count to try and reflect the 'copy/paste but modify' efficiency gain.

Mono-for-Android: 375 lines (575-200)
MonoTouch: 945 lines (1,145-200)

Feature parity
Adjust the MonoTouch solution to allow for the fact that it implements the Map feature that is not available on MonoDroid - 118 lines of code across a few classes.
MonoTouch: 827 lines (945-118)

What's left?
Once we've removed the libraries, the shared data structure, common code and allowed for some "copy/paste re-use", what's left to differentiate the two codebases? Basically just the UI and the code that binds our DTOs to it.
Mono-for-AndroidMonoTouch (iOS)
Code375 lines827 lines
'markup'14 AXML1 XIB
Views7 Activities9 ViewControllers
DataSources6 Adapters5 TableViewSource
Some notes on the difference:
  • There are 350 lines of AXML to define the layouts used in MonoDroid - the equivalent task in MonoTouch is done mostly in C#, significantly contributing to the LOC difference. I could have implemented a lot of that MonoTouch layout in XIBs using InterfaceBuilder - I just don't like doing it that way.
  • The UITabBarController takes more code to setup than
    OnCreateOptionsMenu.
  • The iOS SQLite implementation of saving Favorites is more verbose than the XML-serialized-file solution used on Android.
  • The MonoTouch source is almost 2 years old, and in some places isn't as succinct as it could be.

Conclusion
So is MonoTouch instrinsically more verbose than MonoDroid? I don't think so - it depends greatly on your preference for constructing your Views (XIBs or in-code). The more important question: does building with Mono* make it easier to port your app to other mobile platforms... and the answer is YES! In future this code might get tidied up into a good example of a cross-platform app... in that case I'll re-examine the stats to make an even better case.

Look at it this way: the iOS app took 1,400 lines of code (it was written first). For an additional 375 LOC (plus some layout XML) we got an Android port - almost for free!

Thankfully it sounds like Xamarin Studio is coming along nicely.

Saturday, 9 July 2011

MonoTouch for Monospace II

Further to the MonoDroid version, I've just submitted an iOS version of the Monospace 2011 conference app to Apple (fingers crossed it gets approved, and in time for the conference!).

Here's how it looks:

Even if it doesn't get approved in time, the code is open-source and can be found at github.com/conceptdev/Monospace11. It is based on the original Monospace09, PDC09 and MIX10 apps. A couple of guys helped out with the MIX10 version: @migueldeicaza, @kangamono and @chrisntr. I know Miguel in particular was keen for this code to be open-sourced... I think (?) it was one of the first outings of his awesome MonoTouch.Dialog library. I'd like to thank them again for their help (and to note that any remaining bugs or problems are mine). Also note: there is some old code in there (like, almost 2 years)... it scares me a little to put it up on Github, so please, be gentle.

I'll update with an AppStore link if/when Apple is done; but for now just enjoy the code :)

See you at Monospace!

Wednesday, 6 July 2011

MonoDroid for Monospace

Waay back in 2009 I threw together MonoTouch for Monospace as an early example of using C# on the iPhone using MonoTouch.

Fast-forward two years... to MonoDroid for Monospace:

The schedule for Monospace 2011 was just announced today, and since there didn't seem to be a mobile app announced along with it I've re-used some old code to get a basic Android app working using Mono for Android.

Download/try it out
You can install Monospace11 from the Android Market

OR

Download the Mono for Android code from Monospace11 on Github

and visit the 'homepage' at monospace11.confapp.com

Leave any comments or feedback below.

Saturday, 17 October 2009

MonoTouch for Monospace

MonospaceMonospace is coming up fast, with a whole day's worth of MonoTouch sessions. With that in mind, it seems kinda obvious to make the Monospace schedule available as a MonoTouch app...

Here are some screenshots:



In short, it provides:
  • Conference schedule (day/session/detail views)
  • Speakers (list/detail)
  • Access to the monospaceconf blog
  • Access to @monospace_conf's stream on Twitter
  • A map of the conference location
Some of the fun MonoTouch things I learned along the way include:
  • Creating a UITabBarController in code (no IB)
  • Making icons for UITabBarItem (hint)
  • Creating an 'image watermark' with UIImage behind a UITableView (thanks Mike)
  • Using Linq for Xml to parse Atom feeds (like RSS)
  • Implementing the latest SQLite wrapper from Frank
  • Changing the default UITableViewCell layout in code (eg mutiple lines)
  • Creating a custom UITableViewCell with LoadNib (thanks Simon)
I hope to write some more detail on each of these items... but for now you can download and run the code for yourself:

Monospace2.zip (94Kb)

UPDATE 19-Oct: newer version available
Monospace21.zip (183Kb)

UPDATE 21-Oct: even newer version available
Monospace22.zip (188Kb)

and here's an annotated class diagram/placemat to help make sense of it all:


WARNING: there are plenty of shortcomings/hacks/missing features including: weird lines on the Speaker UITableView, no reloading of data from Blogger or Twitter without restarting, heaps of weird "pointer being freed was not allocated" errors accompanying the SQLite code (only visible in the Application Output window) and probably a pile of bugs I'm not aware of.
USE AT YOUR OWN RISK!