2013年10月30日星期三

The Best PhoneGap Architecture - (4)

Enjoy the art of the coding...

4. Android backbutton handlers

As I know, many PhoneGap APP’s don’t handle android backbutton event. For example, the ones built with jQuery Mobile. When a user taps the backbutton on the android device, the APP just goes back to the previous page, and if no previous page found, the APP exists without a message.
This is absolutely not acceptable for professional PhoneGap developers. Because many pages cannot simply go back, and there should be customizable handlers to handle backbutton event on each page.
Now I’m going to show you how our architecture lets you handle the backbutton so easily.
Firstly, nova.application has an array property named histories that stores all pages except for the index.html. And then, each page (inherited from nova.Page) has an array of backbuttonHandlers. When you press backbutton on the page while the array is empty, the APP will automatically goes back to previous page if there are any in the histories.
You can clear and set nova.application.histories as you wish.
You can go back to a specified page by putting a parameter to nova.application.goback(urlUntil).
You can handle custom backbutton event easily for each page, something like:
Normally, backbutton is widely used on android phones in cases of: remove notification, cancel dialog, cancel progressing bar, etc.
If the handler is not ever needed, then you need to call this.backbuttonHandlers.pop();

nova.application.currentPage

Another property of nova.application. You can access to this object anywhere. It can be used to handle backbutton out of the page definition, instead, can be in helper methods, ect.

Nova.Page.isBackbuttonDisabled

This issued to disable the backbutton on the current page. If it’s set to true, no backbutton handlers will execute. You will find it useful in some situations.

How to test backbutton handler in web browser?

It’s really simple.
Suppose you are using Google Chrome. In the console, enter “cordova.mock.triggerBackbutton()”. It mocks a backbutton event is triggered. You can trigger other events by calling “cordova.mock.trigger(‘menubutton’)”. Of course, you need to using cordova.mock.js instead of cordova.js when testing on web browsers.
You can read another post on how the mock framework works here.

2013年10月25日星期五

The Best PhoneGap Architecture - (3)

Enjoy the art of the coding...

3. Page And APP Navigation

First, JS part.
Here is a very good sample that demonstrats how to make a page and achieve page navigation.
Here is a page named “Menu” that inherits from nova.Page. It’s method onLoaded will be called when the HTML loaded into the #body div.
Please notice the bindClicks events. It demonstrates 4 kinds of page navigation.
  1. Simply go back. (android backbutton can also trigger this).
  2. Go to a simple page
  3. Go to a normal page.
  4. Go to a normal page with parameters.
If you are making a complex page, you can add many more methods to the page prototype object.
More examples:
Then, how is the HTML part?
Second, the HTML Part.
Take a look at the below HTML page.
It’s clean and easy to write. As the basic layout and JS are initialized when APP starts on index.html, the other pages just need to focus on the single page logic. You will love it!
More examples:

The Best PhoneGap Architecture - (2)

In the last post, I described the file structure. In this post, I will describe the shell of the APP.

2. APP Starts And Index.html

Firstly, let’s take a look at the index.html.
This page is a shell of your APP. All JS and CSS are loaded once when the APP starts. You can use this page as a master page of your APP, and you can initialize everything here. After the initialization is done, call: at.start(new at.pages.Home());
Before running the project, you need to merge all the JS files into the "at.all.js". There are many tools can do the merge.
Please notice the scripts links. It’s using jQuery. Don’t worry, the performance is very good after tested on many of our projects. And then the cordova.js, nova framework(nova.all.js), project (at.all.js).
So is this file, very clean.
Here the variable at = nova.application, and extended with other properties. The parameter is a page that inherits from nova.Page. I will describe it how easy to make a page in the next section: APP Navigation
at.js

The Best PhoneGap Architecture - (1)

It's not because it's written by our team, but I do think it is the best I ever work with after trying so many other architectures. Here "other architectures" mean the ones based on libs or frameworks or combine like jQueryMobile, KendoUI, SenchaTouch, AngularJS, BackBone, etc.
Let me show you why it’s the best:

1. Highly Readable Code

A good architecture MUST create clear file structure. The files must be organized very well to keep the code highly readable, which means:
  1. No file have more than 300 lines of code, normally less than 200;
  2. No folder have more than 30 files.
See below screenshot.
How does it look? I believe it looks very clear. All html pages are put into folder “pages”. All project-related javascripts are put into “scripts/at”, and there a few layers to group the JS files. You can easily get to know where to create new files or folders under this architecture.
How this structure can be done? Please read the next section: APP Starts And Index.html

2013年8月14日星期三

How jQuery Mobile Eats PhoneGap Performance, See Experiment


As we know, jQuery Mobile renders a lot of HTML for a simple element/widget. For example, the below picture(from jQM demos) shows the HTML source code (right) of a simple list item(left).
However, to make such a list item, the html can be as simple as just: <li>Acura</li>(don’t know how? Leave a comment.)
But how will HTML elements affect the performance? Let’s take an experiment to see.
I wrote a simple page to test it. Open live demo for web browser(PC & Phone)
 <!DOCTYPE html>  
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1, width=device-width" />
<title></title>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js"></script>
</head>
<body>
<p>
<input type="button" value="Render jQM" id="btnRenderjQM"/>
<input type="button" value="Render Custom" id="btnRenderCustom"/>
</p>
<p><b>Time: </b><span id="time">0</span></p>
<ul id="result" style="height: 200px; overflow: auto;"></ul>
<script language="javascript" type="text/javascript">
var time = null;
$(document).ready(function() {
var li1 = '<li data-corners="false" data-shadow="false" data-iconshadow="true" data-wrapperels="div" data-icon="arrow-r" data-iconpos="right" data-theme="c" class="ui-btn ui-btn-icon-right ui-li-has-arrow ui-li ui-first-child ui-btn-up-c">\
<div class="ui-btn-inner ui-li">\
<div class="ui-btn-text"><a href="#" class="ui-link-inherit">Acura</a></div>\
<span class="ui-icon ui-icon-arrow-r ui-icon-shadow">&nbsp;</span></div>\
</li>';
var li2 = '<li>Acura</li>';
$("#btnRenderjQM").click(function() {
var $ul = $("#result");
$ul.empty();
var html = '';
for (var i = 0; i < 1000; i++) {
html += li1;
}
time = new Date();
$ul.html(html);
$("#time").html(new Date() - time);
});
$("#btnRenderCustom").click(function() {
var $ul = $("#result");
$ul.empty();
var html = '';
for (var i = 0; i < 1000; i++) {
html += li2;
}
time = new Date();
$ul.html(html);
$("#time").html(new Date() - time);
});
});
</script>
</body>
</html>
There are two buttons on the test page, one appends 1000 jQueryMobile list items to the list, while the other appends 1000 simple list items.
Let’s see some charts.
Test in firefox:

Test in google chome:

Test on Android Phone:
The charts mean: HTML elements eat performance. If we use simple HTML elements to render a page, it will save about 80% performance than using jQM. If it’s a small page, that would be OK using jQM, if it’s a complex page, I recommend you write the HTML elements by yourself.
The above test page can be viewed online here: live demo for web browser(PC &Phone).
Feel free to make comments or ask questions.

2013年8月12日星期一

My PhoneGap With jQuery Mobile Development Experience

Recently my PhoneGap team has been working with jQuery Mobile for a few clients. The overall development experience is really bad.

Project 1: tablet

The first APP I want to say is for tablet. Our team joined the development when the APP was about 90% done. That APP used jQuery Mobile and also backbone.
When we joined the development, the code looked not very professional. There are mainly two files for the project, two very big ones. One is the index.html that had over 2000 lines, and the other is index.js that has over 5000 lines of code.
Our first tasks are very small and were done quickly, but we still suffered from the too large code. So we advised the client refactor, and the client accepted. We then re-designed the code architecture and separated the big index.js into many small ones based on functions. The JS code became much clear, but the index.html is still very large(no change).
Later the client said the whole APP performance was not good, then we tried many methods but finally we have to remove usage of jQuery Mobile. It is because jQuery Mobile generates too many html elements for a simple element, such as a button. When the data become a little large, it costs a lot of time rendering so many html element. And the html elements each performance during the whole lifetime of the page.
Another example:
For the above item template, we can change it to:
<li>Acura<span></span></li> , even the <span> is not necessary.
For some pages with big data, we refactored the html to use as few html as possible. And the performance become much better.

Project 2: iPhone

We joined the project also from half way. One of our tasks is to list all contacts and search and choose. Normally, a phone has more than 200 contacts. At the beginning, we used jQuery Mobile listview because the project was already using jQuery Mobile. The list item template is not complex, but the performance was very bad. It cost about 3 seconds to render 300 contacts.
Then we tried removing using listview, instead, we wrote a very simple UL, and the performance become much better. We also spent much time on the listview item template, since it doesn’t work well and not easy to use.
For this project, there are also mainly two big files: index.js and index.html. The code is hard to read or maintain. We need to press CTRL+F to navigate to the right page all the time. It’s really a nightmare.

In conclusion

The two projects originally used a lot of jQuery Mobile features, but finally many of them are removed due to performance issues. I think jQuery Mobile is only suitable for web applications, not for PhoneGap, since performance is really a big concern in PhoneGap.
Till this moment, I haven’t seen any good jQuery Mobile project architecture. A good code architecture should keep the code easy to read, easy to maintain, and any developer knows where to put the code. Generally, each file should have less than 300 lines of code, each method should have less than 30 lines of code.