I've started playing around with Appcelerator Hyperloop. While it seems great to access native APIs from JS from day zero, it does raise a few questions about architecture of the platform and the performance.
Currently (AFAIK) a Titanium app has a main UI thread (that runs the native UI controllers) and a JS thread (that runs the JS logic). Each call from JS to Native is passed though the "Bridge" (which is the expansive operation in an app).
Also, Titanium API doesn't cover all the native API and abstracts as much as it can. But if new APIs are introduced it could take time for Appcelerator to implement those into the platform.
One of my favorite things about Titanium is the ability to extend it (using objective-c for iOS and java for Android) - allowing to use native APIs that are not covered by Titanium, and also developing a really native performance controls in case we need to do anything that's too "heavy" for JS. And, as mentioned it's developed 100% native for each platform.
Now that Appcelerator introduced Hyperloop I've done a simple test app and saw that Hyperloop is not translated into native code but just to normal JS code:
var UILabel = require('hyperloop/uikit/uilabel');
var label = new UILabel();
label.text = "HELLO WORLD!";
$.index.add(label);
And another thing about it is that you have to run on the main thread.
So we basically have a few things come to mind here as far as Hyperloop architecture goes:
We still have a bridge? if Hyperloop is JS that calls "special" Hyperloop require then we still have a bridge, that now not only acts as a bridge but also needs to do some sort of reflection (which is also an expansive operation)?
Until now JS ran in it's own thread - so now running in a single main thread seems to be a potential source to more UI blocking operation.
The old-fashioned modules were truly native (not including the bridge call) - so how do Hyperloop-enabled apps compare with those?
There isn't much documentation or articles about Hyperloop that explain the inner working yet - so if anyone has any answers have been trying apps with it could be very helpful.
Answering your questions straight-forward:
There are no Kroll-Proxies involved anymore, since actual classes are being generated on runtime. This is done by using the hyperloop-metabase that does reflection (as you already said) to build an AST that grabs the actual signatures, types, classes, methods, properties, etc.
We did not see any performance-issues with running on the main-thread for now. If you do so, please file a JIRA-ticket so we can investigate the use-case.
The old-modules were "less native" then now, simply because they were all wrapped by the Kroll-proxy (by extending every view from TiUIView and every proxy from TiProxy / TiViewProxy. Hyperloop does not work with those, making the module-development much more faster by also allowing the developer to test his/her process live in their app without the need of packaging and referencing the module manually. Hyperloop modules are nothing else then CommonJS modules that are already used frequently across Alloy and other Ti-components.
I hope that gives you a quick overview on how Hyperloop works. If you have further questions, let us know!
Hans
(As a detailed answer to the above comment)
So let's say you have a tableview in iOS. The native class is UITableView and the Titanium-API is Ti.UI.TableView / Ti.UI.ListView.
While the ListView already provides a huge performance-boost compared to the TableView by abstracting the Child-API usage to templates, those child-API's (Ti.UI.Label, Ti.UI.ImageView, ...) are still custom classes that are wrapped and provide custom logic (!) e.g. keeping track of it's parent-references, internal data-structures and locks to jump between the threads.
If you now check the Hyperloop example of a native UITableView, you access the native API's directly, so no proxy behind it needs to manage sections, templates, items etc. Of course we deliver that API through a kroll proxy in order to display it in Titanium, but you don't "jump between the bridge" with every call you make from the SDK.
The easiest way to see that is to actually run some bigger example like the tableview, collectionview and view-animation. If you do a fast scroll through these, you already feel the performance boost compared to "classic" Titanium API's, simply because the only communication between your proxy and (like a Ti.UI.Window you want to add it to) is the .add() to receive the native API of the type HyperloopClass.
Finally, of course it still makes sense to use Ti.UI.ListView for example, because it comes with the builtin utilities that Titanium devs love (events, easy configuration and layout-handling). But thats also where the benefit of Hyperloop comes along, by allowing the developer to access those API's him-/herself.
I hope that helps a bit more to understand it.
Related
I'm about to start a new Titanium project. So far, what I've written is what's now considered as "Classic Project" (I've been writing Titanium apps since before Alloy).
I was wondering whether or not it's worth while to switch to Alloy for my new project. I know that basically, Alloy compiles to "Classic" Titanium code before compiling down to the java project or objective-c project. I also know about a big advantage in that "pre-compilation" process, which is to mark in alloy code that are relevant only for Android or iPhone and not including the other in the compiled "Classic" code.
My main concerns are flexibility - as with "Classic" I feel like I have more control over the code and what's going on.
Second concern, I have controls (like open sourced sliding menu) that are not written for alloy - how will I be able to have them as part of my project?
I started asking myself rather to use Alloy or not after finding (introduced in TiConf 2014) TI UX (https://github.com/jaraen/Ti.UX.Templates) which is written for Alloy.
few other questions:
how can I have old UI code run inside Alloy?
Can I have controls written for Alloy run in a "Classic" project?
Can "Classic" project also map out code not belonging to iOS/Android?
is there a difference in performance between Alloy projects and Classic projects? what about other flexibility issues?
Thanks
Just in case someone sees this question and needs an answer:
I have also posted this question in the Appcelerator Q&A where I got some answers here: http://developer.appcelerator.com/question/177739/appcelerator-titanium---alloy-vs-classic
The answer I was given is partial, and more info could be found in a questions asked here: http://developer.appcelerator.com/question/177542/classic-vs-alloy
I felt that the switch to Titanium Alloy from classic was right for me. I felt that classic Titanium development wasn't structured enough nor provided me with enough guidance on a good way to structure my app. Alloy provides a MVC structure to your code, but classic didn't completely prevent you from rolling your own or using one of the community libraries with MVC capabilities. In this respect I guess I would say it is more flexible to use classic over Alloy, because you can choose how to accomplish your structure, rather than fitting into Titanium Alloy's structure. That being said, I've never felt limited by Alloy.
How you develop in Titanium is your preference. There is no right answer to using Alloy or using classic. If one works better for you, use it. I feel that the structured approach to Alloy's separation of display and business logic provides me a structure that makes sense to me when developing an app.
I have not found that Alloy is less flexible than classic. Since you can use classic code in your Alloy project, you can pretty much do everything in Alloy that you can in classic. I'm sure that are some edge cases, that I haven't run into, where one might be easier than another when coding a specific type of application. It may be that classic is less flexible because I don't think you can use Alloy in your classic app. I don't believe the compiler would know how to build that.
Whenever I assess if I'm going to use a particular technology, I make a series of experimental mini programs to make sure all the capabilities are present for my application's requirements. If I feel that it doesn't fit or it is too difficult to reach those requirements, I don't use that technology. For example, when I switched to Alloy, I made sure the Ti.Paint library would still work. If it didn't I would still be using classic.
Just like classic, there are controls for Alloy. There is a pretty slick Alloy-based sliding menu module out there already. I use the Ti.Paint library, which existed before Alloy and isn't an Alloy specific module.
http://gitt.io/ is a decent starting point for finding Alloy modules/widgets.
index.xml
<Alloy>
<Window id="win">
<View id="content" />
</Window>
</Alloy>
1) In your index.js file, you would have the following to use classic coding to manipulate an Alloy view.
index.js
var myview = Ti.UI.createView({
backgroundColor: 'green'
});
$.content.add(myview);
2) I don't think you can use Alloy code in your classic project. As you mentioned before, it needs to do translation on the code and a classic project would likely skip that step in the process.
3) Are you asking if you can include or remove parts of the code based on if it is Android or IOS specific? You could probably do this with include/require statements strategically placed between if (Ti.Platform.osname == "android") statements to require in or not the code you want. If the code is for Android, require this one, if it is for IOS, require in that one.
4) Never attempted to check the performance between classic and Alloy-based projects. I think, since I switched and never noticed an issue that bothers me or my customers, I never put much thought into it. It is entirely possible that Alloy auto-generates code that is in some cases slower. I've never noticed it.
I feel that the efficiency I gain in using Alloy far outweigh that as an immediate concern. Plus, if I felt that I didn't like the way a particular control was created through Alloy, I could use the classic code and define that control myself having all the control of a definition from a classic project.
This one is a quick question regarding the possibility of having the same LnF (same look) on Android and iOS, is there an API that can provide something like this? SImilar to MAUI in MoSync or IwUI in marmaladeSDK?
Basically what I would like to do is to create my UI once for both iOS and Android using monodeveloper.
Note: Before anyone downvotes anymore, please take into account that this is a real requirement for a real project. The question is not without reason, since after looking at the documentation, I can see that Xamarin does not provide such solution, but other multi-platform SDKs do provide such solution, and since the mono ecosystem is vast, perhaps there is a third party library that can provide such functionality.
Unfortunately most of your code portability will be on the backend (non UI) when leveraging Monotouch. There are far too many inconsistencies with how an Android UI vs iOS UI are implemented respectively to their OS's.
Have you checked out http://ifactr.com/overview ? It is a paid product so I haven't tried it, but it might be at least work looking into. Other than this, no there is no cross-platform UI if you go the Mono route.
Taken directly from their page:
"But we learned that even with as much code sharing that MonoCross provides, for applications with significant UI layers, the burden of creating platform-specific UIs can be overbearing. So we created the iFactr UI abstraction layer, which allows developers to code to an abstract UI interface, and then reference our iFactr concrete implementations of that interface for all the mobile platforms, both as native UI implementations and HTML5 UI implementations.
While not a silver bullet for all mobile development, it is designed and optimized for rapidly creating data-driven UIs that enterprise users tend to demand. And because it’s integrated with MonoCross, you can mix-and-match your iFactr UI screens that are shared across platforms with screens that you can code to target specific platforms using the entire set of native APIs available on each mobile OS."
The problem is Android and iOS have different UI / UX metaphors.
Take this for example: http://kintek.com.au/blog/portkit-ux-metaphor-equivalents-for-ios-6-and-android-4/
The differences are fairly significant. If you use a development wrapper then you'll have to 100% rely on their tools. We've had experience with Titanium in the past and it wasn't good at all.
Im new to iPhone development. I come from web-development/design and what bothers me in iPhone development is the unability for custom design... In other words... is there any way I could design my user interface (my view) with webkit so all my UI elemnts would be writen in html/css and logic in objective-c. I was thinking if there is a way I could triger some objective-c code when html button is pressed. Is there any way to do that (lets say via "localhost request" or I dont know) ?
BUT not with phonegap or similar, because then you just start writing your logic in javascript and i dont want that... I want my controller and model to be written in objective-c just the view module in html!
Look into PhoneGap. It has all of the abilities you specify, and can work on Android and other's too (of course you'd need to write the native logic in Java and other languages for that to work though).
The other responders are correct in that efficiency is a big concern, as all of your logic is gated on the Web/native interface. The UIWebView performs a LOT of it's duties on a single thread, and any of your interactions with it must as well.
If you really want to do this, however, there are solutions... Intercepting events from the UIWebView via delegate methods (such as shouldStartLoadWithRequest) that follow a protocol that you define can be used, but I'd suggest either doing everything in JS (trust me, it will actually be faster), or just bite the bullet and learn native iOS development more.
I have a desktop app based on HTML/JS that needs WebKit to function at a reasonable speed. Normally, I would live with IE behaving badly, but its JS engine is just too slow.
I would normally go to Appcelerator for this, but it seems they have discontinued their desktop SDK and left it for the "community"...
This needs to function on Windows PCs, or I would just use Fluid (http://fluidapp.com)...
Is there a simple Webkit wrapper that I can use, or should I build one really quick in something like Qt. I haven't used Qt in a while, so I'd have to look at it again and make sure WebKit is implemented in it...
While it is somewhat node.js-oriented, AppJS may offer what you're looking for. If it doesn't already support other scripting languages, it might at least provide a good example to start from.
Update: in the time that's passed since my original answer, it seems node-webkit fills a similar role but has gathered and maintained more momentum than AppJS. It's a little more focused, in that it doesn't attempt to provide much additional "framework" on top of simply exposing the node.js API to the window's JS context.
There's also https://github.com/atom/atom-shell, which I just learned of and may be similar.
One other thing to note is that (presumably with either, but at least with node-webkit), you MUST be cautious of any XSS-like vulnerability in your app that an attacker could exploit to gain complete access to the user's native machine. So if you are simply needing to package an offline web app in a downloadable desktop distribution, you may wish to research more PhoneGap-like solutions (e.g. Mac OS X as PhoneGap platform) or a plain web view wrapper (like mentioned in the OP) that do not expose an entire OS-level native API — as node.js does — into the JavaScript environment.
I'm developing a phonegap app for iOS, an would like to insert a new option in the context menu that shows up after selecting text. I had a look to several post which are quite related, and almost all of them led to this link. I followed the instructions of that example, but couldn't make it work, due to my lack of experience with Objective-c. Even so, I'm not sure if that one is a valid solution using Cordova/Phonegap, at least without hacking the framework.
Has somebody accomplished this task?