1. More Initialization of MicroJobs.javaThe previous section was a rather long digression into XML Layout files, but as you
can see, that is where a lot of the initialization of the application’s
user interface takes place: where views are defined, named, and given
attributes; where the screen is layed out; and where hints are given to
the layout manager describing the way we would like the screen to look.
Let’s get back to the Java code that brings up the application, starting
where we left off in MicroJobs.java: db = new MicroJobsDatabase(this);
// Get current position
final Location myLocation
= getCurrentLocation((LocationManager) getSystemService(Context.LOCATION_SERVICE));
Spinner spnLocations = (Spinner) findViewById(R.id.spnLocations);
mvMap = (MapView) findViewById(R.id.mapmain);
// get the map controller
final MapController mc = mvMap.getController();
mMyLocationOverlay = new MyLocationOverlay(this, mvMap);
mMyLocationOverlay.runOnFirstFix(
new Runnable() {
public void run() {
mc.animateTo(mMyLocationOverlay.getMyLocation());
mc.setZoom(16);
}
});
Create the database object We said before that we are going to use a small SQLite database to hold
the job, worker, and employer information. The first line
initializes that database by asking Android to create a new
MicroJobsDatabase object (and initialize it).
Get our location We’ll need to know our current location to do things like
finding jobs that are close by, so we get it here by calling
getCurrentLocation, which is a
method defined later and that accepts the name of our
LocationManager as its argument. The
LocationManager is a special class that Android
instantiates for you, and you can retrieve the instance for your
application through the call to getSystemService.
Initialize the Spinner As explained in the previous section, we place a Spinner
widget at the top of the screen to help users quickly go to one of
their favorite locations and look for jobs. This is the first time
we encounter the findViewById
method, which is the way we access the IDs we defined in the XML
layout file. If you recall, we identified the Spinner in main.xml as spnLocations. When we built the
application, Android compiled that XML into a Java identifier that
it placed in R.layout.main.java and linked it into
the application. So now we can use findViewById to connect our Java Spinner
to the XML attributes we defined.
Initialize the MapView and
MapController Similarly,we connect the Java MapView to the attributes
defined for it in main.xml, and then attach a
MapController to it.
Initialize the LocationOverlay We want to create a LocationOverlay
that will build and draw the Map in our
MapView when we want to view a map of our local
area. Again, Maps are covered in much more detail later, but you
can see here that we use the constructor to create a new overlay
and tell it to run when it gets its first fix from the
LocationManager, so that it displays our current location. We also
set the zoom level so it’s about right for a metropolitan
area.
We still need to initialize the remaining
Views on this screen: the Button and the
Spinner. The code for these follows: // Create a button click listener for the List Jobs button.
Button btnList = (Button) findViewById(R.id.btnShowList);
btnList.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(MicroJobs.this.getApplication(),
MicroJobsList.class);
startActivity(intent);
}
});
// Load a HashMap with locations and positions
List<String> lsLocations = new ArrayList<String>();
final HashMap<String, GeoPoint> hmLocations = new HashMap<String, GeoPoint>();
hmLocations.put("Current Location", new GeoPoint((int) latitude, (int) longitude));
lsLocations.add("Current Location");
// Add favorite locations from this user's record in workers table
worker = db.getWorker();
hmLocations.put(worker.getColLoc1Name(), new GeoPoint((int)worker.getColLoc1Lat(),
(int)worker.getColLoc1Long()));
lsLocations.add(worker.getColLoc1Name());
hmLocations.put(worker.getColLoc2Name(), new GeoPoint((int)worker.getColLoc2Lat(),
(int)worker.getColLoc2Long()));
lsLocations.add(worker.getColLoc2Name());
hmLocations.put(worker.getColLoc3Name(), new GeoPoint((int)worker.getColLoc3Lat(),
(int)worker.getColLoc3Long()));
lsLocations.add(worker.getColLoc3Name());
ArrayAdapter<String> aspnLocations
= new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,
lsLocations);
aspnLocations.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spnLocations.setAdapter(aspnLocations);
Create a callback for the btnList Button
View We first get a handle on the Button View by doing a
lookup on its ID, just as we did before for the
Spinner and MapView. We then
set the behavior of the Button, which uses a construct known as a
listener to respond to external
events. When a user clicks a button, Android sends an event to its
OnClickListener
listener. In this code, we set the Button’s behavior by
setting its OnClickListener to
the method that we immediately define, onClick. When the user clicks on btnList, we want to
display a list of available MicroJobs. To do that, we have to
launch a new Activity, MicroJobsList.java, which contains the
screen that displays the list. We can do that by calling the
startActivity method with an
Intent that describes the new Activity. The first statement in
onClick() creates the Intent, using the
constructor for Intents that allows us to explicitly name the
Activity. This constructor takes two arguments: a pointer to the
context of the current application, and the name of the Class to
start. The next statement in onClick() then
uses that Intent to start an instantiation of
MicroJobsList.
Initialize the list of entries in the Spinner View We need two data structures to pass to our Spinner: a list
of favorite locations that
the Spinner will display (and the user can select), and a
hash map connecting location
names to geographical
locations (latitude and longitude). Don’t confuse the HashMap
with a geographical Map; the HashMap uses the term “map”
in the way many programmers use it, to mean an associative
array. We first create the list of location names
(lsLocations), and then the HashMap that we’ll use to
map names to GeoPoints (hmLocations). We then put the
first entry, Current Location, into the list and the
HashMap. This entry will always return the user to the current
location. This item is special because it can be a moving target.
For example, the user may be consulting our application on a
fast-moving train or an airplane, so we have to dynamically
retrieve the location of the device whenever the current location
is selected. We then add three entries for the user’s “favorite
locations,” recorded in the user’s record in the workers table in
the MJAndroid database. We’ll dive into the details of how the
database works and how it’s set up later. For now, we’ll just say
that the code immediately following worker =
db.getWorker(); loads the location names and positions
(latitudes and longitudes) into the lsLocations and
hmLocations
lists. Spinner Views require an ArrayAdapter to feed them the list,
so we create one named
aspnLocations, attaching it to the list of location
names in its constructor. Then, we attach the adapter to the
Spinner by calling setAdapter.
The statement
"aspnLocations.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);"
provides the Spinner with the drop-down layout necessary for the
user to display the whole list of locations. Now that we have initialized the lists, we can add the
following code, which enables the appropriate action when the user
clicks on an item with the Spinner: // Set up a callback for the spinner
spnLocations.setOnItemSelectedListener(
new OnItemSelectedListener() {
public void onNothingSelected(AdapterView<?> arg0) { }
public void onItemSelected(AdapterView<?> parent, View v, int position,
long id) {
TextView vt = (TextView) v;
if ("Current Location".equals(vt.getText())) {
latitude = myLocation.getLatitude();
longitude = myLocation.getLongitude();
mc.animateTo(new GeoPoint((int) latitude, (int) longitude));
} else {
mc.animateTo(hmLocations.get(vt.getText()));
}
mvMap.invalidate();
}
});
}
Initialize the Spinner callback Just as we did with the Button View, we create a method
named onItemSelected and set it
to be called when the user selects an item using the Spinner. The
onNothingSelected method is
also required, but we leave it empty (not used). As mentioned earlier, Current
Location is a special case because we retrieve the
device’s location dynamically when the user selects that item. The
if block handles that case: we
look to see whether the selection is Current Location and if it is, we get
the current location and go there. Otherwise, we go to the
selected location. Then, in the final statement, we invalidate the map so it
will redraw itself.
|