Context

■ Initial Textual Message

■ Indeterminate

■ Cancelable

Using true for the Indeterminate parameter means that we are not providing any clue as to when the operation will complete, such as percentage remaining, just an indicator that something is still happening, which can be a best practice when you don't have a good handle on how long an operation may take. A new Handler G is created to process messages sent from the parsing routine, which is introduced momentarily. An important class that has been mentioned but thus far not described is Message. This class is used to convey information between different threads of execution. The Message class has some generic data members that may be used in a flexible manner. The first of interest is the what member, which acts as a simple identifier, allowing recipients to easilyjump to desired code based on the value of the what member. The most typical (and used here) approach is to evaluate the what data member via a switch statement.

In this application, a Message received with its what member equal to 0 represents a textual update message © to be displayed on the ProgressDialog. The textual data itself is passed as a String cast to an Object and stored in the obj data member of the Message. This interpretation of the what member is purely arbitrary. We could have used 999 as the value meaning textual update, for example. A what value of 1 or 2 indicates that the operation is complete ©, and this Handler can take steps to initiate another thread of execution. For example, a value of 1 indicates successful completion so the ProgressDialog is canceled (dismissed would work here also), and the RefreshJobs Activity is completed with a call to finish(). The value of 2 for the what member has the same effect as a value of 1, but it is provided here as an example of handling different result conditions; for example, a failure response due to an encountered error. In a production-ready application, this step should be fleshed out to perform an additional step of instruction to the user and/or a retry step. Any Message not explicitly handled by the Handler instance should be passed to the super class ©. In this way system messages may be processed.

When communicating with a remote resource, such as a remote web server in our case, it is a good idea to perform the communications steps in a thread other than the primary GUI thread. A new Thread © is created based on the DoReadJobs class, which implements the Runnable Java interface. A new Message object © is instantiated and initialized. This step takes place over and over throughout the run method of the DoReadJobs class. It is important to not reuse a Message object, as they are literally passed and enqueued. It is possible for them to stack up in the receiver's queue, so reusing a Message object will lead to losing data or corrupting data at best and Thread synchronization issues or beyond at worst!

Why are we talking about a commented-out line of code ©? Great question—because it caused so much pain in the writing of this application! A somewhat odd and confusing element of Android programming is the Looper class. This class provides static methods to assist Java Threads to interact with Android. Threads by default do not have a message loop, so presumably Messages don't go anywhere when sent. The first call to make is Looper.prepare(), which creates a Looper for a Thread that does not already have one established. Then by placing a call to the loop() method, the flow of Messages takes place. Prior to implementing this class as a Runnable interface, I experimented with performing this step in the same thread and attempted to get the ProgressDialog to work properly. All this said, if you run into funny Thread/Looper messages on the Android Emulator, have a look at adding a call to Looper.prepare() at the beginning of your Thread and then Looper.loop() to help Messages flow.

When we want to send data to the user to inform him of our progress, we update an instance of the Message class 1) and send it to the assigned Handler.

In order to parse an incoming XML data stream, we create a new InputSource from the URL stream 1!. This step is required for the SAX parser. This method reads data from the network directly into the parser without a temporary storage file.

Note that the instantiation of the JobListHandler takes a reference to the pro-gresshandler. This way the JobListHandler can (optionally) propagate messages back to the user during the parse process. Once the parse is complete, the JobListHandler returns a JobList object, which is then persisted to store the data to the local storage. Because this parsing step is complete, we let the Handler know by passing a Message 1$ with the what field set to a value of 1. If an exception occurs, we pass a message with what set to 2, indicating an error 1%.

Congratulations, your Android application has now constructed a URL with persistently stored configuration information (user and server) and successfully connected over the internet to fetch XML data. That data has been parsed into a JobList containing JobEntry objects, while providing our patient mobile worker with feedback, and subsequently storing the JobList to the filesystem for later use. Now we want to work with those jobs, because after all, those jobs have to be completed for our mobile worker friend to make a living!

0 0

Post a comment