Login     Sign Up
Tugadar Networking Community (@admin)
7 months ago
139 Views

To create user-interface screens for your applications, you extend the Activity class, using Views to provide user interaction.

Each Activity represents a screen (similar to the concept of a Form in desktop development) that an application can present to its users. The more complicated your application, the more screens you are likely to need.

You’ll need to create a new Activity for every screen you want to display. Typically this includes at least a primary interface screen that handles the main UI functionality of your application. This is often sup-ported by secondary Activities for entering information, providing different perspectives on your data, and supporting additional functionality. To move between screens in Android, you start a new Activity (or return from one).

Most Activities are designed to occupy the entire display, but you can create Activities that are semi-transparent, floating, or use dialog boxes.

Creating an Activity

To create a new Activity, you extend the Activity class, defining the user interface and implementing your functionality. The basic skeleton code for a new Activity is shown below:

package com.paad.myapplication;
import android.app.Activity;
import android.os.Bundle;
public class MyActivity extends Activity {
/** Called when the activity is first created. */ @Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
}
}

The base Activity class presents an empty screen that encapsulates the window display handling func-tionality. An empty Activity isn’t particularly useful, so the first thing you’ll want to do is lay out the screen interface using Views and layouts.

Activity UIs are created using Views. Views are the user-interface controls that display data and pro-vide user interaction. Android provides several layout classes, called View Groups, that can contain mul-tiple Views to help you design compelling user interfaces.

Chapter 4 examines Views and View Groups in detail, detailing what’s available, how to use them, and how to create your own Views and layouts.

To assign a user interface to an Activity, call setContentView from the onCreate method of your Activity.

In this first snippet, a simple instance of MyView is used as the Activity’s user interface:

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
MyView myView = new MyView(this);
setContentView(myView);
}

More commonly you’ll want to use a more complex UI design. You can create a layout in code using lay-out View Groups, or you can use the standard Android convention of passing a resource ID for a layout defined in an external resource, as shown in the snippet below:

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
}

In order to use an Activity in your application, you need to register it in the manifest. Add new activity tags within the application node of the manifest; the activity tag includes attributes for metadata such as the label, icon, required permissions, and themes used by the Activity.

An Activity without a corresponding activity tag can’t be started.

The following XML snippet shows how to add a node for the MyActivity class created in the snippets above:

<activity android:label=”@string/app_name”
android:name=”.MyActivity”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” /> <category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>

Within the activity tag, you can add intent-filter nodes that specify the Intents your Activity will listen for and react to. Each Intent Filter defines one or more actions and categories that your Activ-ity supports. Intents and Intent Filters are covered in depth in Chapter 5, but it’s worth noting that to make an Activity available from the main program launcher, it must include an Intent Filter listening for the Main action and the Launcher category, as highlighted in the snippet below:

<activity android:label=”@string/app_name”
android:name=”.MyActivity”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” /> </intent-filter>
</activity>

The Activity Life Cycle

A good understanding of the Activity life cycle is vital to ensure that your application provides a seam-less user experience and properly manages its resources.

As explained earlier, Android applications do not control their own process lifetimes; the Android run time manages the process of each application, and by extension that of each Activity within it.

While the run time handles the termination and management of an Activity’s process, the Activity’s state helps determine the priority of its parent application. The application priority, in turn, influences the likelihood that the run time will terminate it and the Activities running within it.

Activity Stacks

The state of each Activity is determined by its position on the Activity stack, a last-in–first-out collection of all the currently running Activities. When a new Activity starts, the current foreground screen is moved to the top of the stack. If the user navigates back using the Back button, or the foreground Activ-ity is closed, the next Activity on the stack moves up and becomes active. This process is illustrated in Figure 3-7.

As described previously in this chapter, an application’s priority is influenced by its highest-priority Activity. The Android memory manager uses this stack to determine the priority of applications based on their Activities when deciding which application to terminate to free resources.

New Activity

New Activity

started

Figure 3-7

Active Activity

Back button

pushed or

activity closed

Last Active Activity

Removed to

free resources

Previous Activities

Activity Stack

Activity States

As activities are created and destroyed, they move in and out of the stack shown in Figure 3-7. As they do so, they transition through four possible states:

❑Active When an Activity is at the top of the stack, it is the visible, focused, foreground activity that is receiving user input. Android will attempt to keep it alive at all costs, killing Activities further down the stack as needed, to ensure that it has the resources it needs. When another Activity becomes active, this one will be paused.

❑Paused In some cases, your Activity will be visible but will not have focus; at this point, it’s paused. This state is reached if a transparent or non-full-screen Activity is active in front of it. When paused, an Activity is treated as if it were active; however, it doesn’t receive user input events. In extreme cases, Android will kill a paused Activity to recover resources for the active Activity. When an Activity becomes totally obscured, it becomes stopped.

❑Stopped When an Activity isn’t visible, it “stops.” The Activity will remain in memory retain-ing all state and member information; however, it is now a prime candidate for execution when the system requires memory elsewhere. When an Activity is stopped, it’s important to save data and the current UI state. Once an Activity has exited or closed, it becomes inactive.

❑Inactive After an Activity has been killed, and before it’s been launched, it’s inactive. Inactive Activities have been removed from the Activity stack and need to be restarted before they can be displayed and used.

State transitions are nondeterministic and are handled entirely by the Android memory manager. Android will start by closing applications that contain inactive Activities, followed by those that are stopped, and in extreme cases, it will remove those that are paused.

To ensure a seamless user experience, transitions between these states should be invisible to the user.

There should be no difference between an Activity moving from paused, stopped, or killed states back to active, so it’s important to save all UI state changes and persist all data when an Activity is paused or stopped. Once an Activity does become active, it should restore those saved values.

Monitoring State Changes

To ensure that Activities can react to state changes, Android provides a series of event handlers that are fired when an Activity transitions through its full, visible, and active lifetimes. Figure 3-8 summarizes these lifetimes in terms of the Activity states described above.

The following skeleton code shows the stubs for the state change method handlers available in an Activity. Comments within each stub describe the actions you should consider taking on each state change event.

package com.paad.myapplication;
import android.app.Activity;
import android.os.Bundle;
public class MyActivity extends Activity {
Called at the start of the full lifetime. @Override
public void onCreate(Bundle icicle) { super.onCreate(icicle);
// Initialize activity.
}

Called after onCreate has finished, use to restore UI state

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState);
Restore UI state from the savedInstanceState.
This bundle has also been passed to onCreate.
}

Called before subsequent visible lifetimes

for an activity process.

@Override
public void onRestart(){
super.onRestart();
Load changes knowing that the activity has already
been visible within this process.
}

Called at the start of the visible lifetime.

@Override
public void onStart(){ super.onStart();
Apply any required UI change now that the Activity is visible.
}

Called at the start of the active lifetime.

@Override
public void onResume(){
super.onResume();

Resume any paused UI updates, threads, or processes required

by the activity but suspended when it was inactive.

}

Called to save UI state changes at the

end of the active lifecycle.

@Override
public void onSaveInstanceState(Bundle savedInstanceState) { // Save UI state changes to the savedInstanceState.
This bundle will be passed to onCreate if the process is
killed and restarted. super.onSaveInstanceState(savedInstanceState);
}
Called at the end of the active lifetime. @Override
public void onPause(){
Suspend UI updates, threads, or CPU intensive processes
that don’t need to be updated when the Activity isn’t
the active foreground activity.
super.onPause();
}

Called at the end of the visible lifetime.

@Override
public void onStop(){
Suspend remaining UI updates, threads, or processing
that aren’t required when the Activity isn’t visible.
Persist all edits or state changes
as after this call the process is likely to be killed.

super.onStop();
}

Called at the end of the full lifetime.

@Override
public void onDestroy(){
Clean up any resources including ending threads,
closing database connections etc.
super.onDestroy();
}
}

As shown in the snippet above, you should always call back to the superclass when overriding these event handlers.