Sie sind auf Seite 1von 7

Creating an Activity Class

Article from

Unlocking Android

A Developer's Guide
W. Frank Ableson, Charlie Collins, and Robi Sen

MEAP Release: March 2008


Softbound print: March 2009 (est.) | 435 pages
ISBN: 1933988673

This article is taken from the forthcoming book Unlocking Android: A Developer’s Guide from Manning
Publications. A big part of the Android platform revolves around the UI and the concepts of activities and
views. This article explains those concepts and provides practical examples to show how they are created.
For the book’s table of contents, the Author Forum, and other resources, go to
http://manning.com/ableson/.

An Activity is basically analogous to a screen. So to create a screen we will be extending the


android.app.Activity base class and implementing several key methods it defines. Listing 1 shows the first
portion of the ReviewCriteria class, which is used to collect the user’s impression of a restaurant.

Listing 1 The first half of the ReviewCriteria Activity class


public class ReviewCriteria extends Activity { #1

private static final int MENU_GET_REVIEWS = Menu.FIRST;

private EditText location; #|2


private Spinner cuisine; #|2
private Button getReviews; #|2

@Override
public void onCreate(final Bundle savedInstanceState) { #3
super.onCreate(savedInstanceState);

this.setContentView(R.layout.review_criteria); #4

this.location = (EditText) this.findViewById(R.id.location); #|5


this.cuisine = (Spinner) this.findViewById(R.id.cuisine); #|5
this.getReviews = (Button) this.findViewById(R.id.get_reviews_button); #|5

ArrayAdapter<String> cuisines =
new ArrayAdapter<String>(this, R.layout.spinner_view,
this.getResources().getStringArray(R.array.cuisines)); #6
cuisines.setDropDownViewResource(R.layout.spinner_view_dropdown); #7
this.cuisine.setAdapter(cuisines); #8

getReviews.setOnClickListener(new OnClickListener() { #9
public void onClick(View v) {
ReviewCriteria.this.handleGetReviews();
}
});
}

1. Extend android.app.Activity

2. Define Views to use within Activity

3. Override the Activity onCreate() method

4. Define the layout with setContentView

5. Inflate views from XML

6. Define ArrayAdapter instances to bind data, with Context, View, and Array

7. Set the View for the dropdown

8. Associate View and Data using Adapter

9. Add an OnClickListener for our Button

The ReviewCriteria class extends android.app.Activity #1, which does a number of very important
things: first, it gives our application a “context,” because Activity itself extends
android.app.ApplicationContext; second it brings the Android life-cycle methods into play; third it gives
the framework a hook to start and run your application; and lastly it provides a container into which View
elements can be placed.
Because an Activity represents an interaction with the user, in the form of a screen, it needs to provide
components on the screen. This is where views come into play. In our ReviewCriteria class we have referenced
three views in the code: location, rating, and getReviews #2. Location is a type of View known as an
EditText, a basic text entry component. Next, rating is a fancy select list component, known in Android terms
as a Spinner. And, getReviews is a Button.
View elements such as these are placed within an Activity using a particular layout to create a screen.
Layout and views can be defined directly in code, or in a layout XML “resource” file. We will learn more about views
as we progress through this article.

Location as an EditText View

You may be wondering why were are using an EditText View for the “location” field in the ReviewCriteria Activity
when Android includes technology that could be used to derive this value from the current physical location of the
device (or allow the user to select it using a Map, rather than type it in). Good eye, but we are doing this
intentionally here. We want this early example to be complete, and non trivial, but not too complicated. We will
learn more about using the location support Android provides, and MapViews.

After an Activity, complete with necessary views, is started, the life-cycle takes over and the onCreate()
method is invoked #3. This is one of a series of important life-cycle methods the Activity class provides access
to. Every Activity will override onCreate(), where component initialization steps are invoked, though not
every Activity will need to override other life-cycle methods.
Once inside the onCreate() method, the setContentView() method is where you will normally associate an
XML layout view file #4. We say normally, because you do not have to use an XML file at all, you can instead
define all of your layout and View configuration in code, as Java objects. Nevertheless, if is often easier, and better
practice by de-coupling, to use an XML layout resource for each Activity. An XML layout file defines View
objects, which are laid out in a tree, and can then be “set” into the Activity for use.
At this point, all you need to know about views is that they are typically defined in XML, and then are set into
the Activity and “inflated.” Views that need some run time manipulation, such as binding to data, can then be
referenced in code and cast to their respective sub-types #5. Views that are static, i.e. those you don't need to
interact with or update at run time, like labels, do not need to be referenced in code at all (they show up on the
screen, because they are part of the View tree as defined in the XML, but need no explicit setup in code). In Figure
1, you will notice that the ReviewCriteria screen has two labels, as well as the three inputs we have already
discussed. These labels are not present in the code, they are defined in the “review_criteria.xml” file that we will
see coming up when we discuss XML-defined resources.

Figure 1. High level diagram of Activity, View, resources, and manifest relationship showing that activities are made up of views,
and views use

The next area of our ReviewCriteria Activity is where we bind data to our select list views, the Spinner
objects. Android employs a handy “adapter” concept to link views that contain collections with data. Basically an
Adapter is a collection handler that returns each item in the collection as a View. Android provides many basic
adapters: ListAdapter, ArrayAdapter, GalleryAdapter, CursorAdapter, and more. And, you can also
easily create your own, but that is beyond the scope of this article. Here we are using an ArrayAdapter that is
populated with our Context (this), a View element defined in an XML resource file, and an array representing
the data (also defined as a resource in XML) #6. When we create the ArrayAdapter we define the View to be
used for the element shown in the Spinner before it is selected. After it is selected it uses the View defined in
the “dropdown” #7. After our Adapter, and its View elements are defined, we then set it into the Spinner
object #8.
The last thing this initial Activity demonstrates is our first explicit use of event handling. UI elements in general
support many types of events. In this case we are using an OnClickListener with our Button, in order to
respond when the button is clicked #9.
After the onCreate() method is complete, with the binding of data to our Spinner views, we next have some
menu buttons (which are different than on-screen Button views, as we shall see) and associated actions, we see
how these are implemented in the last part of ReviewCriteria in listing 2.

Listing 2 The second half of the ReviewCriteria Activity class

. . .

@Override
public boolean onCreateOptionsMenu(final Menu menu) { #1
super.onCreateOptionsMenu(menu);
menu.add(0, ReviewCriteria.MENU_GET_REVIEWS, 0, R.string.menu_get_reviews).
setIcon(android.R.drawable.ic_menu_more);
return true;
}

@Override
public boolean onMenuItemSelected(final int featureId, final MenuItem item) { #2
switch (item.getItemId()) {
case MENU_GET_REVIEWS:
this.handleGetReviews();
return true;
}
return super.onMenuItemSelected(featureId, item);
}

private void handleGetReviews() { #3


if (!this.validate()) {
return;
}

RestaurantFinderApplication application = (RestaurantFinderApplication)


this.getApplication(); #4
application.setReviewCriteriaCuisine(this.cuisine.getSelectedItem().toString());
application.setReviewCriteriaLocation(this.location.getText().toString());

Intent intent = new Intent(Constants.INTENT_ACTION_VIEW_LIST); #5


this.startActivity(intent); #6
}

private boolean validate() {


boolean valid = true;
StringBuffer validationText = new StringBuffer();
if ((this.location.getText() == null) ||
this.location.getText().toString().equals("")) {
validationText.append(this.getResources().getString(R.string.location_not_supplied
_message));
valid = false;
}
if (!valid) {
new AlertDialog.Builder(this).setTitle(this.getResources()
.getString(R.string.alert_label)).setMessage(
validationText.toString()).setPositiveButton("Continue", #7
new android.content.DialogInterface.OnClickListener() { #8
public void onClick(final DialogInterface dialog, final int arg1) {
}
}).show();
validationText = null;
}
return valid;
}
}

1. Create options menu


2. Respond when menu item is selected
3. Create method to process getting reviews and moving to next screen
4. Use the android.app.Application object for state
5. Create an Intent
6. Start an Activity
7. Use an AlertDialog – again notice builder pattern
8. Respond to button click with anonymous ClickListener

The menu items seen at the bottom of the Activity screens in figure 2 are all created using the
onCreateOptionsMenu() method #1. Here we are using the Menu class add() method to create a single
MenuItem element #1. We are passing a group ID, an ID, order, and a text resource reference to create the
menu item. We are also then assigning an icon to the menu item via the setIcon method. The text and the image
are externalized from the code, again using Android's concept of resources. The MenuItem we have added
duplicates the on-screen Button with the same label for the “Get reviews” purpose.
Figure 3.2 RestaurantFinder application screen shots, showing three Activities: ReviewCriteria, ReviewList, and ReviewDetail.

Using the Menu versus on screen Buttons

We have chosen to use the Menu here, in addition to the on screen Button Views. Though either (or both) can
work in many scenarios, you need to consider whether the menu, which is invoked by pressing the menu button
on the device and then tapping a selection (button and a tap) is appropriate for what you are doing, or if an on-
screen Button (single tap) is a better choice. Generally on-screen Buttons should be tied to UI elements (a search
button for a search form input, for example), and menu items should be used for screen wide actions (submitting
a form, performing an action like “create,” “save,” “edit,” or “delete”). Yet, because all rules need an exception, if
you have the screen real estate, it may be more convenient for users to have on-screen Buttons for actions as
well, as we have done here. The most important thing to keep in mind with these type UI decisions is to be
consistent. If you do it one way on one screen, use that same approach on other screens within your application.
In addition to creating the menu item, we also add support to react and perform an action when the item is
selected. This is done in the onMenuItemSelected() event method #2, where we parse the ID of the available
menu items with a case/switch statement. When the MENU_GET_REVIEWS item is determined to have been
selected, we then call the handleGetReviews method #3. This method puts the logic to save the user’s selection
state in the Application object #4, and then sets up to call the next screen. We have moved this logic into its own
method because we are using it from multiple places, from our on-screen Button, and again from our MenuItem.
The Application object is used internally by Android for many purposes, and can be extended, as we have
done with RestaurantFinderApplication (which simply includes few member variables in JavaBean style), to
store global state information. We will reference this object again from other Activities to retrieve the information
we are storing here. There are several ways to pass objects back and forth between Activities, using Application
is one of them. You can also use Android Preferences to pass objects between activities within an application,
but again these are limited to primitive and String types. Additionally, you can use the provided SQLite database,
or you can implement your own ContentProvider and store data there. Lastly, an Intent can be passed
between Activities to share data – particularly data that does not need to be long-lived. The important thing to
take away here is that we are using the Application object to pass state between activites.
After we store the criteria state we then fire off an action in the form of an Android Intent #5; basically we
are asking another Activity to respond to the user's selection of a menu item by calling
startActivity(Intent intent) #6.

Using startActivity versus startActivityForResult

The most common way to invoke an Activity is by using the simple startActivity()
method, but there is also another method you will see used in specific instances –
startActivityForResult(). Both of these pass control to a different Activity. The
difference with regard to “For Result” is that it returns a value to the current Activity
when the Activity being invoked is complete. It in effect allows you to chain Activities
and expect callback responses. The result of a called Activity is obtained by a
“callback” method you must implement named onActivityResult.
Also of note within the ReviewCriteria example is that we are using an AlertDialog #7. Before we allow
the next Activity to be invoked, we call a simple validate() method that we have created, where we display a
pop-up style alert dialog to the user if the location has not been specified. Along with generally demonstrating the
use of AlertDialog, this also again demonstrates how a button can be made to respond to a click event with an
OnClickListener() #8.

The Builder Pattern

You may have noticed the usage of the Builder pattern when we added parameters to the AlertDialog we
created in the ReviewCriteria class. If you are not familiar with this approach, basically each of the methods
invoked, such as AlertDialog.setMessage(), and AlertDialog.setTitle() returns a reference to
itself (this), which means we can continue chaining method calls. This avoids either an extra long constructor
with many parameters, or the repetition of the class reference throughout the code. Intents make use of this
handy pattern too; it is something you will see time and time again in Android.

We have covered a good deal of material and have completed our first Activity – ReviewCriteria! This class
is now fully implemented.

Das könnte Ihnen auch gefallen