My FMX application is coming along nicely, many of the issues have been fixed.
I’ve just begun work on the Articles section so it’s rough.
There’s still quite a bit to do, including work on the theme and icons.
It is much more performant and responsive now.
FMX Project Framework
What I set out to do in building this application was to determine if FMX was a viable option for creating mobile applications.
The second objective was to create a robust framework which could be reused for subsequent projects of similar structure, of which I have a few in mind.
This is the project structure to date:
All the tricks and workarounds for working with the various platforms are in the Utils folder.
The Data folder should probably be renamed to Models since the units contain entities and repositories. Strictly speaking this is a violation of SOLID, but acceptable in this case.
For example, the uProfile unit contains the profile entity:
And the repository:
Using this unit is simple:
for Profile in Profiles.FindAll do begin... Profiles.Delete(SelectedProfileId); var Profile := Profiles.Add(name); FProfile.Answer[id] := IsChecked;
There is one main form which is used to host individual views, a controller is responsible for managing the views and application navigation:
For an example of the type of Navigation services offered by the controller see here.
This is the function which creates views, the Id is used to identify a persisted view:
T is constrained in the interface section:
function CreateView<T:TView>(AId: TViewId): T;
And the code which docks a view:
An unanticipated change of view happens due to two events:
- User Input
- The OS puts the app in the background
Both these cases are managed. The view gets a chance to apply changes as it is notified of navigation events, such as the back button was pressed, and its state is also managed when moving to the background. The code could be evolved to give the currently docked view a chance to cancel the switch, but that’s a trivial change since the structure is already in place.
The main form delegates persistence of state to the controller which works with the active view:
Or in the case of recovery, to restore the persisted view and its state:
The views all inherit from the TView base class:
Lastly, individual UI elements are created as frames each with their own behaviour. The views are composed of these frames. This high cohesion and low coupling makes it very simple to maintain the code base. It also takes advantage of the UI designer in Delphi.
I love the separation of code and UI Delphi affords, it keeps the code clutter free.
For example, the UI and class definition for TPictureFrame:
There’s actually very little to the views. Consider this view which allows the user to select an image:
It has this UI structure – it’s a TFrame descendant with a TVertScrollBox:
And just these few lines of code behind:
That’s the beauty of Delphi, it offers great support for component based design.
I prefer event based architectures like Delphi to reactive. You have so much freedom to design the application in the way you see fit, there’s few constraints, and state managements is simple.
I also appreciate how easy it is to apply professional styling. Delphi ships with a number of nice styles, but there are other providers available.
FMX is very flexible. Any control can parent other controls, placing them relative to itself. That’s on top of a comprehensive layout system, and controls like TLayout and TFrame. Animations and effects are also simple to employ. Here’s a contrived example of creating a reusable button:
The rectangle is the parent of the controls, GlowButton is just a TFrame host enabling reuse:
Think WPF flexibility with WinForms simplicity.
Vidi Veni Vici
It has been fun, I like using FMX.
The project has been coming along, but I must say FMX lacks the stability and polish of the VCL.
It seems Embarcadero is committed to the Desktop First approach – which makes sense given Delphi’s strengths and history.
But I do hope they continue to invest in FMX, it has a lot of potential in an IoT world.