- Appcelerator Titanium Smartphone App Development Cookbook(Second Edition)
- Jason Kneen
- 769字
- 2021-07-30 10:09:36
Speeding up your remote data access with Yahoo YQL and JSON
If you are already familiar with using JavaScript heavily for the Web, particularly when using popular libraries such as jQuery or Prototype, then you may already be aware of the benefits of using JSON instead of XML. The JSON data format is much less verbose than XML, which means that file size is smaller and data transfer is much faster. This is particularly important when a user on a mobile device may be limited in data speed due to network access and bandwidth.
If you have never seen Yahoo!'s YQL console or heard of the YQL language web service, note that it is essentially a free web service that allows developers and applications to query, filter, and combine separate data sources from across the Internet.
In this recipe, we are going to use the Yahoo! YQL console and web service to obtain data from our recipes' data feed, and transform that data into a JSON object, which we'll then bind to our TableView.
How to do it...
First of all, go to Yahoo!'s YQL console page by opening http://developer.yahoo.com/yql/console in your browser. Change the show tables
text in the SQL statement field to select * from feed where url='http://rss.allrecipes.com/daily.aspx?hubID=79'
. Select the JSON button and then hit Test. You should see a formatted set of data returned in the results window, in JSON format!

To use this data, we need to copy and paste the complete REST query from the YQL console. This is right at the bottom of the browser and is a single-line textbox. Copy and paste the entire URL into your xhr.open()
method, replacing the existing recipes' feed URL.
Note
Make sure that when you paste the string, it hasn't broken due to any apostrophes. If it has, you'll need to escape the apostrophe characters by replacing them with \
. Alternatively, you can wrap the string in instead of, and it will parse correctly. See the next example code.
Now, back in the xhr.onload()
function, let's replace the content of the refresh
function with the following, which will parse JSON instead of XML:
var data = []; //empty data array //declare the http client object var xhr = Ti.Network.createHTTPClient(); //this method will process the remote data xhr.onload = function() { //create a json object using the JSON.PARSE function var jsonObject = JSON.parse(this.responseText); //print out how many items we have to the console console.log(jsonObject.query.results.item.length); //loop each item in the json object for (var i = 0, j = jsonObject.query.results.item.length; i < j; i++) { //create a table row var row = Ti.UI.createTableViewRow({ hasChild: true, className: 'recipe-row', backgroundColor: '#fff', // for Android filter: jsonObject.query.results.item[i].title //this is the data we want to search on (title) }); //title label var titleLabel = Ti.UI.createLabel({ text: jsonObject.query.results.item[i].title, font: { fontSize: 14, fontWeight: 'bold' }, left: 70, top: 5, height: 20, width: 210, color: '#000' // for Android }); row.add(titleLabel); //pubDateLabel label var pubDateLabel = Ti.UI.createLabel({ text: jsonObject.query.results.item[i].pubDate, font: { fontSize: 10, fontWeight: 'normal' }, left: 70, top: 25, height: 40, width: 200, color: '#000' }); if (pubDateLabel.text == '') { pubDateLabel.text = 'No description is available.'; } row.add(pubDateLabel); //add our little icon to the left of the row var iconImage = Ti.UI.createImageView({ image: 'food_icon.png', width: 50, height: 50, left: 10, top: 10 }); row.add(iconImage); // save an instance of the row data against the row row.data = jsonObject.query.results.item[i]; //add the table row to our data[] object data.push(row); } //finally, set the data property of the tableView //to our data[] object tblRecipes.data = data; }; //this method will fire if there's an error in accessing //the remote data xhr.onerror = function() { //log the error to our console console.log(this.status + ' - ' + this.statusText); }; //open up the recipes xml feed xhr.open('GET', "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20feed%20where%20url%3D'http%3A%2F%2Frss.allrecipes.com%2Fdaily.aspx%3FhubID%3D79'&format=json&diagnostics=true&callback="); //finally, execute the call to the remote feed xhr.send();
How it works...
As you can see in the preceding recipe, accessing the YQL web service is simply a matter of passing an HTTP GET
query to the YQL service URL, using a YQL
statement as a URL
parameter. When it processes a query, the Yahoo! YQL service obtains and transforms the requested data, and returns it in your specified format (JSON in our case).
Accessing the properties of the JSON data object is also different from XML, and arguably much simpler. In JSON, we use simple dot notation to navigate through the data tree hierarchy and select the property that we want to use. If you are already familiar with array syntax in PHP, JavaScript, and a number of other C-Style languages, this should also be pretty familiar to you!