One Codebase for Desktop and Mobile in Rad Studio with FMX and FireDAC
Keep business logic in shared FireDAC DataModules and UI in FireMonkey FMX, with platform style hooks. Use LiveBindings and IFDEFs to isolate variance for Windows, macOS, iOS and Android.
05 Jul 2026, 20:24 UTC

Maintaining one business codebase for Windows desktop and macOS/iOS/Android while keeping acceptable native feel and reliable data access is the core multi-device problem in Rad Studio. The useful takeaway is to centralize logic in shared DataModules backed by FireDAC and keep UI in FireMonkey FMX with platform style hooks, gating only small variances with conditional compilation.
Reuse line: FMX UI plus shared DataModules
FireMonkey is a custom-drawn framework. The same FMX form compiles to Windows, macOS, iOS and Android, with platform styles applied at runtime. That gives visual consistency without duplicating forms. Data access is kept separate in a DataModule that uses FireDAC components. FireDAC provides a common API across database engines and platforms, with connection pooling and cached updates that help with offline resilience.
Shared UI with platform style hooks
FMX controls are not native widgets. They are rendered by the FMX style system. You can ship a base style and override specific style elements per platform. Style changes are applied without code changes, which reduces branching. Platform differences such as safe area insets on mobile or DPI scaling on desktop are handled by FMX layout and by querying platform services through IFDEFs.
Data access that stays the same with FireDAC
A shared DataModule can host TFDConnection, TFDQuery and TFDTable. Connection parameters can be set at runtime per target. FireDAC supports cached updates, which allows edits to be staged locally and applied later. UpdateOptions on TFDQuery control how changes are generated. TFDMonitor in the IDE can show the SQL that FireDAC emits, which is a practical way to verify behavior without assuming output.
Declarative wiring with LiveBindings
LiveBindings connects data fields to visual controls declaratively. For a list, a TListView can be bound to a query field list. Binding expressions are version-sensitive and the designer surface changes across releases, so verify binding behavior in your edition.
Isolating variance with IFDEFs
Platform symbols such as ANDROID, IOS, MSWINDOWS, MACOS are available at compile time. Gate small platform-specific code with IFDEFs rather than duplicating units. Example pattern in a shared unit:
{$IFDEF ANDROID}
// Android-specific file access path
Path := TPath.GetDocumentsPath;
{$ENDIF}
{$IFDEF MSWINDOWS}
// Windows-specific path handling
Path := GetUserDir;
{$ENDIF}
Inspect Project > Options > Compiling > Conditional defines to confirm which symbols are defined for each target. Required permissions are IDE project edit rights. Risk: symbol names differ between Delphi and C++Builder and change across versions, so do not hard-code assumptions.
Worked example: master-detail orders viewer
Create a Multi-Device Application FMX project. Add a DataModule with TFDConnection named FDConn, TFDQuery named qryCustomers and TFDQuery named qryOrders. Set qryCustomers to select customers and qryOrders to select orders filtered by customer id. Enable cached updates on qryOrders via UpdateOptions.
On the main form place a TListView for customers and a TListBox for orders. Use LiveBindings to bind ListView Items to qryCustomers fields CustomerID and Name. Bind ListBox to qryOrders. On selection change, reparameterize qryOrders and refresh.
Minimal conditional code is used for file-based database location:
{$IFDEF ANDROID}
DBPath := TPath.Combine(TPath.GetDocumentsPath, 'app.db');
{$ENDIF}
{$IFDEF MSWINDOWS}
DBPath := TPath.Combine(GetUserDir, 'app.db');
{$ENDIF}
FDConn.Params.Database := DBPath;
Build the same project for Windows and an enabled mobile target. Observe style changes and control rendering differences. Check Tools > Options > SDK Manager to confirm mobile SDKs are installed and enabled for your edition. Feature availability varies by Rad Studio edition; FMX mobile targets and FireDAC drivers require Professional or higher and installed SDKs.
Trade-off: custom-drawn controls vs native feel
FMX provides custom-drawn controls, not true native widgets. This increases testing surface and can create accessibility gaps and platform-specific rendering quirks, especially on mobile with C++Builder. Input methods, keyboard handling and gesture expectations differ per OS. Plan explicit validation on each target rather than assuming parity.
Actionable setup to validate reuse
Start with a shared DataModule and keep all SQL and business rules there. Isolate UI variance in FMX styles and small IFDEF blocks. Use GetIt packages for platform libraries only when needed. Gate platform code with IFDEFs and validate deployment with the IDE's multi-target build. Test FireDAC cached updates by setting TFDQuery.UpdateOptions and inspecting generated SQL with TFDMonitor in the IDE. This gives a practical check that reuse is working without inventing test results.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.