It may seem strange to hear the term "behavior" applied to applications, but it is very appropriate. Applications, if designed incorrectly, can potentially waste systemwide resources and therefore hurt the performance of the device as a whole. The application framework classes do not take care of good behavior for you ”it is up to you to ingrain this in your applications. This section provides general guidelines to ensure that your application serves its users well, but not to the detriment of the device in general.
You will need a skeptical mindset when designing and writing applications. Always take into consideration how your application would react in undesirable, unexpected or rare circumstances. Cast a critical eye upon all code as you write it, and continually ask yourself questions like: "What would happen to my application if the device ran out of memory?", "What would happen if my application were requested to go into the background?", and "What would happen if the battery were suddenly removed?" Under all such circumstances, you should strive to create the best possible outcome for the user , without affecting other applications, or the OS.
There are several different types of Window Server events, such as key events, system events and foreground events, which must be handled appropriately. The AppUi class has several functions that are called by the Window Server to handle each type of event notification ”these were previously overviewed in the Important AppUi Methods subsection.
What you do within these overridden functions is up to you, but the following discussion details some likely scenarios and suggests ways to handle events responsibly.
It is possible for an application to gain or lose focus at any time. This can happen if the user switches between applications, or if the system brings another application into the foreground. Whenever an application's window group gains or loses focus, the application UI's HandleForegroundEventL() method will be called. This method has a single TBool parameter, which will be ETRue if the application is gaining focus and EFalse if it is losing focus.
When an application loses the foreground, it must strive to establish a stable, recoverable state. This means suspending all processing and saving application data ”for two reasons. First, processing power must be reserved for the foreground application. It is of primary importance, because it is the application with which the user interacts . If background applications were to continue processing, users might experience an unwanted reduction in performance. Second, background-running applications may be automatically shutdown by the system in low memory conditions. If a forced shutdown were suddenly to occur, and background applications were to continue processing, it might not be possible to establish a steady and recoverable state.
User input must also be handled correctly. When the user carries out an action on the user interface, an event will be sent to the application that owns the window the event occurred in. There are several different types of events, but you will be interested mainly in key events and redraw events. (These are discussed further in Chapter 5.) Good programming behavior recommends that you take into consideration not only the key presses you expect, but also those that you do not.
Your application needs to exit gracefully. Exiting can be initiated explicitly by users, or automatically by the system. Under these circumstances, an EEikCmdExit instruction will be received by HandleCommandL() . This is a last opportunity to save application data and to release system resources that are no longer required. Note that applications must shutdown quickly once they receive this command ”there is no time to present options to the user.
It is also possible that the entire system may be shutdown before your application is closed. This could happen, for example, if the user turned off the device, or if the battery was removed accidentally . You must consider the impact of a sudden shutdown on application data. Consider what would happen if the ShapeDrawer application were suddenly interrupted . If it was in the background at the time, no data would be lost, because HandleForegroundEventL() forces a save of the data at this time. But if the user had added new shapes to the document since application startup and the application had been running in the foreground the entire time, sudden interruption could cause the user's newly entered shapes to be lost. One way around this would be to update the document every time the user inputs a new shape. Although this approach minimizes the amount of data that is likely to be lost, it carries a high performance cost. When designing applications, you need to be aware that performance and data security are two competing aims, and that you need to strike a balance according to your application's requirements.
Saving data must be performed responsibly. When the file system becomes too full, it can have a negative affect on system performance. Therefore, all applications must aim to prevent this from happening by checking available disk resource levels before committing data memory. The ShapeDrawer application accomplishes this by using the SysUtil::DiskSpaceBelowCriticalLevelL() utility function, defined in sysutil.h .
This function's return value tells you whether writing x bytes to a particular drive will cause disk space to drop below a critical level. Do not ignore this function when it returns Etrue ”losing your application's data is preferable to potentially corrupting the file system.
File System ” When using files, minimize the number of opening, reading and writing instructions. Write larger data blocks in one go. Persisting one large block of data is much more efficient than multiple writes of smaller blocks of data. As mentioned in the previous subsection, check the free disk space available using the methods provided in SysUtil .
System Watchdogs ” There are subsystems within Series 60 that may request that your application exit at any time ”for example, the OOM (Out-Of-Memory) Watchdog. This closes down background applications under conditions of low memory.
Reserve the EEikCmdExit command for system-generated exit requests . When your application is requested to exit by the system, save data, if necessary, and exit the application without any UI confirmation queries . The urgency of this message precludes the possibility of presenting options to users before shutting down.
Hard-Coding and Magic Numbers ” Avoid these at all costs. Examples of data that are frequently hard-coded are directory paths, key codes, calculation variables and so on.
You should use the AknUtils API CompleteWithAppPath() (as described in the SDK documentation) to access data files within the user data area, without assuming that your application is installed on any particular drive. Also, do not assume that z: is the system drive ”instead, use BaflUtils::GetSystemDrive().
Use header files to share constants, and resource files to provide all user-visible text, as explained in the Internationalization section. Also, always query the system for values whenever possible ”for example, to obtain screen sizes ”rather than hard-coding such values.
Timers ” Do not use continuous, fast-ticking timers. All continuous timers ticking faster than once every five seconds are problematic ”they can continually interrupt the device from its low-power mode and shorten battery life. Remember to stop all timers and pause the application when it goes into the background.
Active Objects and Responsiveness ” If an application hangs , or otherwise does not respond for more than ten seconds, then the View Server will terminate it ”so ensure you do not have long-running active objects.