The tutorial will cover the following topics:
- Activity component callbacks during launching an App and quitting an App
- App State persistence across re-starts
- Activity component callbacks for Menu creation and event handling
- Navigation from the main screen of the Activity to another screen within the Activity
For sake of simplicity, the code is all present in one 'SampleActivity' class. I fought the serious Enterprise Java OCD urge to refactor it into a thousand very small beautiful tightly knit classes communicating with each other via some serious architectural layers (ahem...wrappers) ;)
App Launch
When the App is launched, it fires up the registered Activity. This is registered in the AndroidManifest.xml file. According to the Activity component lifecycle, onCreate is invoked during initial activation. The main responsibility of this phase is to do some state management. This could be loading the state of the App from a local cache, inflating Layouts from the various screens, etc.
Source Code:
protected void onCreate(Bundle savedInstanceState)
{
try
{
//This must be invoked..otherwise the Android runtime
//will throw an exception
super.onCreate(savedInstanceState);
//Load some App state information that is stored in a
//simple cache. This information survives App re-starts
this.loadCache();
//Get the layout information for the home screen
Integer homeScreenLayoutId = R.layout.home;
//Get the layout information for the next screen
Integer nextScreenLayoutId = R.layout.nextscreen;
this.cache.put("home", homeScreenLayoutId);
this.cache.put("nextscreen", nextScreenLayoutId);
}
catch(Exception e)
{
//Show an error screen and exit
this.getErrorDialog("System Error",
e.toString()).show();
}
}When the App state is fully loaded it should display the UI associated with the activity. This happens during the onResume invocation on the component.
Source Code:
protected void onResume()
{
try
{
//This must be invoked..otherwise the Android runtime
//will throw an exception
super.onResume();
//Find and render last active screen
String active = (String)this.cache.get("active");
if(active != null)
{
if(active.equals("home"))
{
this.renderHomeScreen();
}
else
{
this.renderNextScreen();
}
}
else
{
//render the home view
this.renderHomeScreen();
}
}
catch(Exception e)
{
//Show an error screen and exit
this.getErrorDialog("System Error",
e.toString()).show();
}
}
Here the onResume method decides which one of the Activity's screen it should render.
Quitting an App
When the Activity is closed, the Android runtime invokes the onDestroy method to allow the App to
do some state management and cleanup.
Source Code:
protected void onDestroy()
{
try
{
//This must be invoked..otherwise the Android runtime
//will throw an exception
super.onDestroy();
//Saving the App State
this.saveCache();
}
catch(Exception e)
{
//Handle Exception..App is being destroyed...
//in case of an error, let the platform
//handle it with a system message
throw new RuntimeException(e);
}
}
Here, its saves the Cache instance so that when the App is launched again, the currently active screen is the one that is rendered.Note: Besides the onCreate, onResume, and onDestroy invocations covered in this tutorial, there are other callback invocations as well. A detailed explanation of the entire Activity lifecycle is covered here
App State Persistence across restarts
This activity remembers the currently active screen upon closing. When the App is launched again, its resumes the Activity at this point.
It does this by storing a pojo Cache instance inside the SharedPreferences object. The SharedPreferences class in Android provides a general framework that allows you to save and retrieve persistent key-value pairs of primitive data types.
Source Code:
private void loadCache() throws Exception
{
SharedPreferences local = this.getPreferences(0);
this.cache = new Cache();
String home = local.getString("home", "");
String nextscreen = local.getString("nextscreen", "");
String active = local.getString("active", "");
if(home != null && home.trim().length()>0)
{
cache.put("home", new Integer(Integer.parseInt(home)));
}
if(nextscreen != null && nextscreen.trim().length()>0)
{
cache.put("nextscreen",
new Integer(Integer.parseInt(nextscreen)));
}
if(active != null && active.trim().length()>0)
{
cache.put("active", active);
}
}
private void saveCache() throws Exception
{
//Load the SharedPreferences Editor
SharedPreferences local = this.getPreferences(0);
SharedPreferences.Editor editor = local.edit();
//Store the 'home' layout id
Integer home = (Integer)cache.get("home");
if(home != null)
{
editor.putString("home", ""+home);
}
//Store the 'nextscreen' layout id
Integer nextscreen = (Integer)cache.get("nextscreen");
if(nextscreen != null)
{
editor.putString("nextscreen", ""+nextscreen);
}
//Store the 'active' screen, this can be used
//to display this screen when the
//App is launched again
String active = (String)cache.get("active");
if(active != null)
{
editor.putString("active", active);
}
//commit the changes
editor.commit();
}
App Menu
The Android runtime invokes onCreateOptionsMenu to give the Activity a chance to create the App Menu. The menu is launched in response to the 'Menu' key on the device.
Source Code:
public boolean onCreateOptionsMenu(Menu menu)
{
try
{
//Inflate the layout for the menu.
//The xml is stored in res/menu/app_menu.xml
MenuInflater inflater = getMenuInflater();
Integer app_menu_id = R.menu.app_menu;
inflater.inflate(app_menu_id, menu);
return true;
}
catch(Exception e)
{
return false;
}
}
It invokes onOptionsItemSelected as an event handler in response to the selection of one of the 'Menu' items.Source Code:
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle item selection
switch (item.getItemId())
{
case R.id.hello:
Toast.makeText(this, "Hello World!!!",
Toast.LENGTH_SHORT).show();
return true;
case R.id.quit:
this.finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Configuration
- AndroidManifest.xml: App configuration where the components are configured
- res/layout/home.xml: Layout configuration for the Home screen of the app
- res/layout/nextscreen.xml: Layout configuration for the Next screen of the app
- res/menu/app_menu.xml: App Menu configuration
Enjoy!!!
ShareThis
the call to getString( "home", "" ), returns a empty string (default param) if "home" is not defined previously. Why you check home != null?
ReplyDeleteSame with the nextscreen and active strings.
you are correct. The 'null' check is not necessary.
ReplyDeleteIf you're using Eclipse you can just make a "new Android App" and copy in the files above, but you will also need the Cache.java file! You can unzip the Maven file and grab it from there.
ReplyDelete