This software article series can be applied to gadget/widget programming, and is exemplified on Google Desktop gadgets.


Proper Offline Behaviour

Teodor Filimon, Gadget Developer
November 2007
"Something cannot emerge from nothing."  -  Frank Herbert

Introduction

More and more gadgets, especially in the Web 2.0 era, have to communicate with the online world to provide fresh data and interactivity between users. But at the same time, unlike a web based gadget, a desktop gadget also has to know what to do when the user is offline.

Detection

First of all, we have to realise that gadgets can do a lot of things while online, like fetching news, feeds or images and interacting with other users of the same gadget. So, depending on what we use the gadget for, there are several ways to see if the computer is online or offline:

More about offline and online detection can be found in JAMES' ARTICLE (NEED LINK).

Interface Issues

Ultimately, the user has to see what's going on, but the changes in the interface should be suggestive - as you can see in Figure 1, the most important UI element (big red heart), which would also have no use if Google Talk wasn't running, is replaced by an appropriate message.

What to do when Google Talk is not running and/or not installed
Figure 1: Telling the user what to do

Notice how the gadget neither pops out an error which requires immediate attention, nore gives a message like "Error 235: Connection not found" :) Instead it focuses on guiding the user to make the most out of this gadget. Considering the features you're implementing, you can go further by applying diferent modes to the interface (much like it is described in this article), so, for example, when the user goes offline, the gadget will discard the visual space taken by the online functionality.

Data Handling

You've made a gadget that gets news, or latest posts in a feed, or just parses a big XML file. It has to fetch the items on open and after that periodically to keep the data fresh. But what if the next time our gadget will be opened there won't be an internet connection? The best solution is remembering the item array using options. But going even further with the worst case scenario, another question comes to mind: how can i efficiently remember object arrays in the options dictionary? Fortunately there is a solution to this too, and it doesn't involve remembering the entries separately, but all in one string. For this, you can use JSON, a cool data-interchange format. Basically it helps you convert an object (including an array) into a string and back again.

A good example of array memorising is in the Tabbed ToDo List LINK NEEDED gadget. You can see exactly what functions to call for the both-way conversion (array to string and string to array). The tasks, tabs and checkbox values are succesively memorized and recreated using JSON.

function change(){
	//memorizes the new todolist
	options("todoList")=todoList.toJSONString();
	options("tabs")=tabs.toJSONString();
	options("values")=values.toJSONString();
	//todoList, tabs and values are all arrays
}

function show(){
	//shows the remembered todo list
	todoList=options("todoList").parseJSON();
	values=options("values").parseJSON();
	tabs=options("tabs").parseJSON();
	//...
}

These functions are defined in a .js script file downloadable at the JSON site. That script has to be included in your main.xml file just as you include main.js.

Good Practices

We've seen how to optimize gadget behaviour accross sessions, but we can't forget about the CPU and memory usage which always have to be very efficient.

Where the CPU is concerned, a specific process that often occurs in programming a gadget is sorting an array. Depending on the array dimensions you choose one of the sorting methods that best suite your case. The sorting is mostly necessary because you always want the user to be presented with items of interest (unchecked tasks in a to-do list, unread items in a news feed, etc.). In such cases don't forget about the Ranking API, which sorts items based on various criteria like number of clicks, publishing time or others. So when you'll use this ranking engine, you won't have to write the actual sorting, but just choose some filters.

But of course the most expensive activity in terms in CPU is one that is repeated periodically. The Javascript methods setInterval and setTimeout are widely used, but they have to used carefully. For example, infinite call cycles should be avoided and timers should be destroyed when they're not used - it's action doesn't necessarily have to be done if it isn't useful.

function myFunction(){
	alert("Alert");
}

token=setInterval("myFunction()",10000);
//this timer will call myFunction once every 10 seconds

//when the timer isn't needed it should be deleted
//we can do this using the token returned by setInterval
clearInterval(token);
//you can also delete a timeout, using clearTimeout

You can find out more about these functions, including some that can be particularly helpful when animations are created, by checking out the documentation for the view object.

Similar safeguards should be used to optimize memory usage as well. Declaring variables locally, in functions, is usually better then keeping them global (of course, sometimes that can't be avoided :). Objects should also be deleted or made void if they aren't used anymore. A good example are audioclips. Once they have been played, their variables should be set to null if they are of no more use.

Conclusion

Every environment has it's own rules, workarounds, safeguards and best practices. It's important to know them and to apply them when needed, to create the best application possible.

Many gadgets, everyone!

Resources


Author Bio

Teodor Filimon

I'm a natural born programmer. My first contact with a techno-gadget was Star Trek (remember those cool sensors?). I used to fill up a whole room with drawings of them when I was only 3 years old. Generally, I find a lot of inspiration for intuitive interfaces in things with "star" in their names (like Star Wars, Stargate,... :-) . I like the border between interface and function—it's the essence of a program, I think. Anyway, I'm a software engineering student now, and you can learn more about me and what I'm thinking and doing at my website or blog. My most popular gadgets are DigiWatch and TV Set.