Running jQTouch in PhoneGap | October 28th, 2009
Update: the content of this post is no longer relevant. The gap has been filled.
Last week there were some discussions about the poor performance of jQTouch in PhoneGap apps, so I dug into it.
First I had to verify that this was something we were doing in PhoneGap and not a difference between Mobile-Safari and the UIWebView control which we use in PhoneGap.
I created a PhoneGap project and dropped the jQTouch sample code into the www folder, and immediately noticed the sluggish performance.
I then created a bare bones iPhone Windowed application with a UIWebView in it, and dropped the same www folder contents into the project root.
NSURL *appURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"index" ofType:@"html" inDirectory:@"www"]];
NSURLRequest *appReq = [NSURLRequest requestWithURL:appURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
[webView loadRequest:appReq];
After running both builds on the device it was obvious that the PhoneGap version was in fact sluggish compared to the bare-bones version. Verified!
So, thinking about what could be causing this, I looked into the PhoneGapDelegate code, and immediately saw the Accelerometer handling code the a potential culprit. The PhoneGapDelegate class asks the sharedAccelerometer for updates 40x per second. According to the Applei Phone dev docs, this interval is “Suitable for games and other applications that use the accelerometers for real-time user input.” Which is cool, but probably way more than this application needs considering it isn’t even being used. Every time that the sharedAccelerometer calls back with an update, the javascript is written into the webView’s DOM. Commenting out the accelerometer code that sets up the interval indeed fixes the majority of the sluggishness. Verified! Pretty smooth, eh?
Okay, so commenting it out isn’t really a solution, so here is the plan:
I am working to re-implement the Accelerometer portion as a command, that can be used more elegantly. Javascript code inside the www folder should have the ability to set how frequently it wants be updated, and have the ability to start + stop monitoring the accelerometer, which should also remove the overhead.
Note:
If your application does not use the accelerometer, instead of commenting out the code like I did, you can simply set “EnableAcceleration” to false in PhoneGap.plist.
I will post an update here when I have checked in anything of significance.
October 28th, 2009 at 9:36 am
I will test this on my own, but for the benefit of other readers I thought I should ask:
1) Will setting EnableAcceleration to false prevent the UndoManager from displaying the Undo confirmation dialog when the user shakes the phone?
2) Will setting EnableAcceleration to false prevent navigator.accelerometer.watchAcceleration() from working?
TIA
October 28th, 2009 at 9:46 am
Can’t say thanks enough for looking into this. I’m also curious about Jon’s questions, but it sounds like a great fix for simple apps.
October 28th, 2009 at 10:29 am
I will be checking in a better solution tomorrow. As for your questions Jonathan,
1) I am not sure, will have to test.
2) Yes, if EnableAcceleration is false, then navigator.accelerometer.watchAccelerometer() will fail. Although because of the way the JS is currently implemented, there will be an interval firing and calling your callback with bogus data.
Another thing I am looking at adding is a capabilities object that would carry info on what API’s are supported by the currently running host.
October 28th, 2009 at 7:25 pm
That’s very good news!
Thanks for looking into this and finding a solution so quickly.
October 28th, 2009 at 9:48 pm
I just tested my app and it does perform much better when I set EnableAcceleration to false! Although it’s still a bit less responsive than the Mobile Safari version. Maybe there’s another tweak to get a bit more performance out of it?
October 29th, 2009 at 1:37 am
Thanks so much for looking into this and figuring it all out. I immediately saw a dramatic performance increase.
I noticed you used terms like “majority of the sluggishness.” Is there something else going on that you think might be contributing?
October 29th, 2009 at 2:30 am
Cameron, It still feels like it takes a long time between when you press a link/button and when you see the state change to active. This is still consistent with what I see in an app using a straight up UIWebView, so it is probably not a PhoneGap issue.
October 29th, 2009 at 6:09 am
[...] can read Jesse McFayden’s post here. And if you’ll excuse me, I have an app to finish… Filed under: Tips, mobile [...]
October 29th, 2009 at 8:49 pm
Thanks for the hint but it did not change anything for the web app I am currently working on.
I am using jQTouch and also experience intervals of 1-2 seconds when tapping on a link when using Phonegap here (using an iPhone 3G device) … definitely quite unresponsive from an end-user perspective.
The web app itself is at least twice as responsive as the Phonegap app.
This makes Phonegap pretty useless for me for the time being … unfortunately.
It would be nice to try to solve these issue as jQTouch + Phonegap are indeed an interesting approach to web app / native app development.
November 12th, 2009 at 4:56 pm
To Sergio da Silva: Do you use a regular link ? If yes, try to capture ontouch event instead. Worked for me. Sometimes the normal links don’t work at all.