Alloy XML vs Imperative UI: Choosing the Right Pattern in Titanium SDK
A practical comparison of Alloy XML declarative layout versus Ti.UI.createView imperative code in Titanium SDK, with a worked example, dynamic list patterns, SDK version cautions, and verification steps.
14 Jun 2026, 00:33 UTC

Alloy XML vs Imperative UI: Choosing the Right Pattern in Titanium SDK
You’re staring at a new screen in a Titanium project, debating whether to wire UI components declaratively with Alloy XML or imperatively with Ti.UI.createView. The choice affects event handling, dynamic list rendering, and how the code scales as features grow. For most screens, Alloy XML reduces boilerplate and pairs naturally with collections for dynamic lists, while imperative code gives fine-grained control for runtime-generated hierarchies.
Declarative layout with Alloy XML
Alloy’s <Alloy> tag in a TSS/ XML file defines UI components and automatically wires their IDs and events to a JavaScript controller. You don’t need to call Ti.UI.createView, assign an ID, and add an event listener in separate statements. Instead, the XML declares the hierarchy, and the controller receives a global object whose properties mirror the XML elements. Property wiring – Alloy maps an XML element’s id attribute to $.idName in the controller, so you can set $.button.title = 'Save' directly in JavaScript.
Dynamic lists with Alloy collections
When you need to populate a TableView or ListView from remote data, Alloy collections streamline the pattern. Define a collection in the controller, fetch JSON via Ti.Network.createHTTPClient, and bind the result to the table. The performance tip from the SDK docs recommends reusing Ti.UI.Window instances and avoiding view creation inside tight loops; instead, toggle visibility or update collection data. This keeps the UI thread light and avoids memory churn.
function loadUsers() {
var client = Ti.Network.createHTTPClient();
client.open('GET', 'https://api.example.com/users');
client.onload = function() {
var data = JSON.parse(this.responseText);
// Simplified binding; actual collection logic depends on SDK version
$.userTable.setData(data.map(function(row) {
return Ti.UI.createTableViewRow({ title: row.name });
}));
};
client.onerror = function() {
Ti.API.info('Failed to load users');
};
client.send();
}
When imperative Ti.UI.createView makes sense
- Runtime-determined component hierarchies, such as dynamically generated forms based on server-defined schemas.
- Integrating third-party libraries that expect Ti.UI objects created purely in JavaScript.
- Complex conditional logic that adds or removes subviews after the initial layout.
The trade-off is more boilerplate: each view requires an ID, an event binding, and an explicit add() call to parent it. For screens where the layout is static or only mildly dynamic, Alloy XML usually wins on maintainability.
Performance, SDK version & verification
The SDK cautions note that native modules compiled for SDK 10.x may fail on SDK 12+ due to API changes. Always rebuild native modules with the target SDK version. To verify, run:
- Run
ti build -p android --loglevel=debugfrom the project root (requires Titanium CLI installed and platform SDKs configured). - Check the console for
'Alloy compiled XML successfully'. - Inspect the generated
AndroidManifest.xmlfor the correct<meta-data>entries matching the native module. - Use
Ti.API.infoafter invoking a native method to confirm the return value matches your expected output.
If the build log references SDK version mismatches, rebuild with ti build -p android --sdk 12.0.0 (replace with your target version) and re-check the manifest. If the rebuild fails, rebuild with the previous SDK version using ti build -p android --sdk 10.3.0 and verify the module’s entry point again.
Risks: Using an incompatible SDK version for native modules can cause runtime crashes or missing platform APIs. The rebuild commands modify the AndroidManifest and compiled binaries; rolling back to a previous SDK version restores compatibility if the new version introduces breaking changes.
Start with Alloy XML for standard screens. If you need runtime component generation, fall back to imperative Ti.UI.createView but keep window reuse in mind. Always rebuild native modules with the target SDK version and verify the debug log confirms successful compilation.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.