• 沒有找到結果。

Multithreaded Execution

在文檔中 Learning Android (頁 133-137)

A much better solution is to run the potentially long operations on a separate thread.

When multiple tasks run on multiple threads at the same time, the operating system slices the available CPU time so that no one task dominates the execution. As a result, it appears that multiple tasks are running in parallel at the same time.

In our example, we could put the actual network call for updating our status in the cloud in a separate thread. That way our main UI thread will not block while we’re waiting for the network, and the application will appear much more responsive. We tend to talk of the main thread as running in the foreground and the additional threads as running in the background. They’re really all equal in status, alternating their execution on the device’s CPU, but from the point of view of the user, the main thread is in the foreground because it deals with the UI. Figure 7-18 shows the execution of our code’s two threads

—the main UI thread, as well as the auxiliary thread we use to perform potentially long-running network calls.

Threading in Android | 115

Figure 7-18. Multithreaded execution

There are several ways to accomplish multithreading. Java has a Thread class that allows for many of these operations. We could certainly use any of the regular Java features to put the network call in the background.

However, using the standard Java Thread class is somewhat problematic. Imagine that after we post to the cloud we want to notify the user of the success or failure of that operation. We would have to update the UI. But, in Android, a thread that didn’t create the UI widget is not allowed to update the UI—this would not be thread-safe. We would need to synchronize these threads somehow, and that would be a job on its own.

Because this is a common task in Android, the framework provides the utility class AsyncTask specifically designed for this purpose.

AsyncTask

AsyncTask is an Android mechanism created to help handle long operations that need to report to the UI thread. To take advantage of this class, we need to create a new subclass of AsyncTask and implement its doInBackground(), onProgressUpdate(), and onPostExecute() methods. In other words, we are going to fill in the blanks for what to do in the background, what to do when there’s some progress, and what to do when the task completes.

We’ll extend our earlier example with an asynchronous posting to the cloud. The first part of Example 7-6 is very similar to the code in Example 7-4, but hands off the posting to the asynchronous task. A new AsyncTask does the posting in the background.

Example 7-6. StatusActivity.java, version 2

package com.marakana.android.yamba;

import android.app.Activity;

import android.os.AsyncTask;

import android.os.Bundle;

import android.util.Log;

import android.view.Menu;

public class StatusActivity extends Activity implements OnClickListener { private static final String TAG = "StatusActivity";

private EditText editStatus;

private Button buttonTweet;

@Override

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

super.onPostExecute(result);

public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.status, menu);

return true;

} }

Once we have our AsyncTask set up, we can run it. To do so, we simply instantiate it and call execute() on it. The argument that we pass in is what goes into the doInBackground() call. Note that in this case we are passing a single string that is being converted into a string array in the actual method later on, which is an example of Java’s variable number of arguments feature. It is important to remember that this method executes on a separate thread, so you cannot update the UI from it.

The PostTask class in this case is an inner class of StatusActivity. It also subclasses AsyncTask. Notice the use of Java generics to describe the data types that this AsyncTask will use in its methods. We’ll explain these three types following this list. The first data type is used by doInBackground(), the second by onProgressUpdate(), and the third by onPostExecute().

doInBackground() is the callback that specifies the actual work to be done on the separate thread, acting as if it’s executing in the background. The argument String… is the first of the three data types that we defined in the list of generics for this PostTask inner class. The three dots indicate that this is an array of Strings, and you have to declare it that way, even though you want to pass only a single status.

This is the call to the Yamba Client library that does all the magic of encoding it into a web service call. We’re passing the first parameter of the input, which is the actual text of the status that comes in via the execute() call from on Click().

onPostExecute() is called when our task completes. This is our callback method to update the user interface and tell the user that the task is done. It is important to know that this method executes on the application’s main thread, which we also refer to as the UI thread.

In this particular case, we are using a Toast feature of the Android UI to display a quick message on the screen. Notice that Toast uses the makeText() static method to make the actual message. Also, do not forget to include show();

otherwise, your message will never be displayed, and no error will be reported

—a hard bug to find. The argument that this method gets is the value that doInBackground() returns, in this case a string. This also corresponds to the third generics data type in the PostTask class definition. The reference to Sta tusActivity.this represents the Context that our application is in. As a rule of thumb, whenever in an activity, pass that activity as the context object.

At this point, when the user clicks “Update Status,” our activity creates a separate thread using AsyncTask and places the actual network operation on that thread. When done, the AsyncTask will update the main UI thread by popping up a Toast message to tell the user that the operation either succeeded or failed.

在文檔中 Learning Android (頁 133-137)