Understanding Views and Windows in Titanium Mobile
Problem Definition
When I’m implementing items in titanium I have an option to create a new view or create a window. It would be good to know what the consequences are for using one vs the other and how an application collaborates across views/windows.
Context
When you implement views or windows in Titanium, you can do so by providing a HTML resource as the parameter to create the corresponding view or window. Titanium in turn creates either:
- window – a new window with a single webview in it
- view – adds the view to the window parameter’s stack of views
If you call the titanium window’s open() method with {modal:true}, the new window will be presented modally, IE, coming up from the bottom. This is mostly a behavioral difference, however, as unlike the horizontal push, there is no back button, and it hides the tab bar. This is due to what Apple’s SDK has.
In the beginning, a webView and a window were a single class. As of 0.5 or so, when TableView came about, Window and webView split ways. For backwards compatibility reasons, when you supply an url to a window on creation (Or, technically, all the way up till opening) a nameless webView is created and added. You can even see it or grab it when you use a window’s getViews() method. It’s done on the Objective-C side, but the javascript is the effect of:
1 2 3 4 | if(this.url){ var webView = Ti.UI.createWebView({url:this.url}); this.addView(webView); } |
Technically speaking, as of 0.8, the only thing that has a context is the web views. Windows may contain web views that have contexts, but windows, tableViews, groupedViews, scrollableViews, imageViews, Buttons, sliders, etc, do not have any javascript context, but instead are controllable by the web views, and thus, that’s why they can see each other is that they’re all in the same web view context.
One thing that does improve performance and flexibility is to move more creation into one context. For example:
file1.html:
1 2 | var newWin = Ti.UI.createWindow({url:'file2.html'}); newWin.open(); |
file2.html:
1 2 3 | var table = Ti.UI.createTableView({...}); Ti.UI.currentWindow.addView(table); Ti.UI.currentWindow.showView(table); |
singleFile.html:
1 2 3 4 5 | var newWin = Ti.UI.createWindow({}); var table = Ti.UI.createTableView({...}); newWin.addView(table); newWin.showView(table); newWin.open(); |
Using file1.html, you have to generate a new web view (implicitly), wait for it to load, including the rather hefty JS injection, then load in all of data and such before the table shows. Using singleFile, the table is immediately there, even as the animation takes place revealing the new window. The only drawback is that focused events don’t fire on newWin when it should, and a few other bugs that should be addressed.
Going into 0.9, moving more and more code into fewer, more concentrated contexts is the way to get speed, but even now, it can offer some boosts.
Trade offs
It’s important to understand what the trade offs are from one to another
| function | windows | views |
|---|---|---|
| multiple animation styles when showing | nope (only allow from left or none and from bottom when modal). | yip (all sorts of animation styles and parameters provided) |
| visibility to binded objects in javascript environment | nope, objects are not shared across windows | yip – depending on the type of view. for example a tableview will have access to the parent window’s javascript objects as explained above |
| consume/publish to same event manager | nope | yip events are delivered in the same eventing domain |
| automatic navigation bar integration | yip – you can define the traits for a window when you create it (title, back button title, etc) of course navigation is not shown if the window is opened modally | nope, the views share the same fixed navigation for the window they belong to, you can manipulate the nav bar, but this isn’t really the same |
| coordinate with tabs | yip | nope |
Storing state
If you want to exchange state between 2 windows, then you cannot bind them into a transient javascript object because they are out of scope and do not have visibility to each other’s environment. However, you can make use of Application properties or use a database to persist your state for visibility across windows. When you serialize to/from a string property you can use the JSON representation of the object you are persisting to enable complex objects (this is what we do a lot).
Transitioning between views/windows
In the case where you have 2 views and you want to define interactions you can either:
- call a method in the javascript environment
- fire a custom event and consume it in a listener
The above implementations demonstrate a powerful advantage views have over windows, however you can still get around this with window-2-window communication. In either a webview or a window, you can add a listener to the current windows focus event, for example:
1 2 3 | Titanium.UI.currentWindow.addEventListener('focused', function() { ... }); |
Then in the listener you could look for a object stored in the state identified above. In this scenario, one window would store a persistent object when something happens and then when the other window recieves the focus, it would look up this object, notice the state change and perform some behavior.
Wrap up
Understanding the differences between when to use views and when to use windows is important as well as some of the creative work arounds needed to facilitate interactions in your application. We hope you’ve found this useful and encourage you to reach out to us via email if you are in need of any services while building titanium applications.
Thanks for the info. I was using only windows and never any views till I came across this post.