1. Trang chủ
  2. » Công Nghệ Thông Tin

Lập trình Androi part 22 potx

6 233 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Dealing with Threads
Trường học University of Technology
Chuyên ngành Computer Science
Thể loại Bài tập lớn
Năm xuất bản 2025
Thành phố Hanoi
Định dạng
Số trang 6
Dung lượng 238,75 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

This generally means that there will need to be some coordination between background threads doing the work and the UI thread showing the results of that work.. Getting Through the Handl

Trang 1

155

Dealing with Threads

Ideally, you want your activities to be downright snappy, so your users don’t feel that

your application is sluggish Responding to user input quickly (e.g., within in 200

milliseconds) is a fine goal At minimum, though, you need to make sure you respond

within 5 seconds, lest the ActivityManager decide to play the role of the Grim Reaper

and kill off your activity as being nonresponsive

Of course, your activity might have real work to do, which takes nonnegligible amount of

time This invariably involves the use of a background thread Android provides a

veritable cornucopia of means to set up background threads, yet allow them to safely

interact with the UI on the UI thread

The “safely interact” concept is crucial You cannot modify any part of the UI from a

background thread That must be done on the UI thread This generally means that there

will need to be some coordination between background threads doing the work and the

UI thread showing the results of that work

This chapter covers how to work with background and UI threads in your Android

applications

Getting Through the Handlers

The most flexible means of making an Android-friendly background thread is to create

an instance of a Handler subclass You need only one Handler object per activity, and

you do not need to manually register it Merely creating the instance is sufficient to

register it with the Android threading subsystem

Your background thread can communicate with the Handler, which will do all of its work

on the activity’s UI thread This is important, as UI changes, such as updating widgets,

should occur only on the activity’s UI thread

You have two options for communicating with the Handler: messages and Runnable

objects

15

Trang 2

Messages

To send a Message to a Handler, first invoke obtainMessage() to get the Message object out of the pool There are a few flavors of obtainMessage(), allowing you to create empty Message objects or ones populated with message identifiers and arguments The more complicated your Handler processing needs to be, the more likely it is you will need to put data into the Message to help the Handler distinguish different events

Then you send the Message to the Handler via its message queue, using one of the sendMessage () family of methods, such as the following:

 sendMessage(): Puts the message on the queue immediately

 sendMessageAtFrontOfQueue(): Puts the message on the queue immediately, placing it at the front of the message queue, so your message takes priority over all others

 sendMessageAtTime(): Puts the message on the queue at the stated time, expressed in the form of milliseconds based on system uptime (SystemClock.uptimeMillis())

 sendMessageDelayed(): Puts the message on the queue after a delay, expressed in milliseconds

To process these messages, your Handler needs to implement handleMessage(), which will be called with each message that appears on the message queue There, the

handler can update the UI as needed However, it should still do that work quickly, as other UI work is suspended until the Handler is finished

For example, let’s create a ProgressBar and update it via a Handler Here is the layout from the Threads/Handler sample project:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>

<ProgressBar android:id="@+id/progress"

style="?android:attr/progressBarStyleHorizontal"

android:layout_width="fill_parent"

android:layout_height="wrap_content" />

</LinearLayout>

The ProgressBar, in addition to setting the width and height as normal, also employs the style property This particular style indicates the ProgressBar should be drawn as the traditional horizontal bar showing the amount of work that has been completed

And here is the Java:

package com.commonsware.android.threads;

import android.app.Activity;

import android.os.Bundle;

import android.os.Handler;

Trang 3

import android.os.Message;

import android.widget.ProgressBar;

public class HandlerDemo extends Activity {

ProgressBar bar;

Handler handler=new Handler() {

@Override

public void handleMessage(Message msg) {

bar.incrementProgressBy(5);

}

};

boolean isRunning=false;

@Override

public void onCreate(Bundle icicle) {

super.onCreate(icicle);

setContentView(R.layout.main);

bar=(ProgressBar)findViewById(R.id.progress);

}

public void onStart() {

super.onStart();

bar.setProgress(0);

Thread background=new Thread(new Runnable() {

public void run() {

try {

for (int i=0;i<20 && isRunning;i++) {

Thread.sleep(1000);

handler.sendMessage(handler.obtainMessage());

}

}

catch (Throwable t) {

// just end the background thread

}

}

});

isRunning=true;

background.start();

}

public void onStop() {

super.onStop();

isRunning=false;

}

}

As part of constructing the Activity, we create an instance of Handler, with our

implementation of handleMessage() Basically, for any message received, we update the

ProgressBar by 5 points, and then exit the message handler

In onStart(), we set up a background thread In a real system, this thread would do

something meaningful Here, we just sleep 1 second, post a Message to the Handler, and

repeat for a total of 20 passes This, combined with the 5-point increase in the

Trang 4

ProgressBar position, will march the bar clear across the screen, as the default

maximum value for ProgressBar is 100 You can adjust that maximum via setMax() For example, you might set the maximum to be the number of database rows you are processing, and update once per row

Note that we then leave onStart() This is crucial The onStart() method is invoked on

the activity UI thread, so it can update widgets and such However, that means we need

to get out of onStart(), both to let the Handler get its work done and also so Android does not think our activity is stuck

The resulting activity is simply a horizontal progress bar, as shown in Figure 15–1

Figure 15–1 The HandlerDemo sample application

Note, though, that while ProgressBar samples like this one show your code arranging to update the progress on the UI thread, for this specific widget, that is not necessary At least as of Android 1.5, ProgressBar is now UI thread-safe, in that you can update it from any thread, and it will handle the details of performing the actual UI update on the

UI thread

Runnables

If you would rather not fuss with Message objects, you can also pass Runnable objects to the Handler, which will run those Runnable objects on the activity UI thread Handler offers a set of post () methods for passing Runnable objects in for eventual

processing

Trang 5

Running in Place

Just as Handler supports post() and postDelayed() to add Runnable objects to the

event queue, you can use those same methods on View This slightly simplifies your

code, in that you can then skip the Handler object However, you lose a bit of flexibility

Also, the Handler has been in the Android toolkit longer, and it may be more tested

Where Oh Where Has My UI Thread Gone?

Sometimes, you may not know if you are currently executing on the UI thread of your

application For example, if you package some of your code in a JAR file for others to

reuse, you might not know whether your code is being executed on the UI thread or

from a background thread

To help combat this problem, Activity offers runOnUiThread() This works similar to the

post() methods on Handler and View, in that it queues up a Runnable to run on the UI

thread, if you are not on the UI thread right now If you are already on the UI thread, it

invokes the Runnable immediately This gives you the best of both worlds: no delay if

you are on the UI thread, yet safety in case you are not

Asyncing Feeling

Android 1.5 introduced a new way of thinking about background operations: AsyncTask

In one (reasonably) convenient class, Android will handle all of the chores of doing work

on the UI thread versus on a background thread Moreover, Android itself allocates and

removes that background thread And it maintains a small work queue, further

accentuating the fire-and-forget feel to AsyncTask

The Theory

There is a saying, popular in marketing circles: “When a man buys a 1/4-inch drill bit at a

hardware store, he does not want a 1/4-inch drill bit—he wants 1/4-inch holes.”

Hardware stores cannot sell holes, so they sell the next-best thing: devices (drills and

drill bits) that make creating holes easy

Similarly, Android developers who have struggled with background thread management

do not strictly want background threads Rather, they want work to be done off the UI

thread, so users are not stuck waiting and activities do not get the dreaded “application

not responding” (ANR) error And while Android cannot magically cause work to not

consume UI thread time, it can offer things that make such background operations

easier and more transparent AsyncTask is one such example

To use AsyncTask, you must:

 Create a subclass of AsyncTask, commonly as a private inner class of

something that uses the task (e.g., an activity)

Trang 6

 Override one or more AsyncTask methods to accomplish the background work, plus whatever work associated with the task that needs to be done on the UI thread (e.g., update progress)

 When needed, create an instance of the AsyncTask subclass and call execute() to have it begin doing its work

What you do not need to do is:

 Create your own background thread

 Terminate that background thread at an appropriate time

 Call all sorts of methods to arrange for bits of processing to be done

on the UI thread

AsyncTask, Generics, and Varargs

Creating a subclass of AsyncTask is not quite as easy as, say, implementing the

Runnable interface AsyncTask uses generics, and so you need to specify three data types:

 The type of information that is needed to process the task (e.g., URLs

to download)

 The type of information that is passed within the task to indicate progress

 The type of information that is passed when the task is completed to the post-task code

What makes this all the more confusing is that the first two data types are actually used

as varargs, meaning that an array of these types is used within your AsyncTask subclass This should become clearer as we work our way toward an example

The Stages of AsyncTask

There are four methods you can override in AsyncTask to accomplish your ends

The one you must override, for the task class to be useful, is doInBackground() This will

be called by AsyncTask on a background thread It can run as long as necessary in order

to accomplish whatever work needs to be done for this specific task Note, though, that tasks are meant to be finite; using AsyncTask for an infinite loop is not recommended The doInBackground() method will receive, as parameters, a varargs array of the first of the three data types listed in the preceding section—the data needed to process the task So, if your task’s mission is to download a collection of URLs, doInBackground() will receive those URLs to process The doInBackground() method must return a value

of the third data type listed—the result of the background work

Ngày đăng: 01/07/2014, 21:20

TỪ KHÓA LIÊN QUAN