作者givemepass (〆)
看板AndroidDev
标题[分享] Painless threading (翻译版)
时间Wed Mar 9 23:21:35 2011
最近执行绪有一些问题,因此找了一些资料,
刚好看到这一篇文章,因为是原文的,想说翻译起来可以让有需要的人参考,
如果翻错或者不是那麽正确,请千万一定要让我知道,避免误导大家,谢谢。
原文连结
http://android-developers.blogspot.com/2009/05/painless-threading.html
Painless threading
无痛执行绪
Posted by Romain Guy on 06 May 2009 at 9:30 AM
Whenever you first start an Android application, a thread called "main" is
automatically created.
每当你一开始启动android应用程式,
会有一个叫做main的执行绪自动地被产生。
The main thread, also called the UI thread, is very important because it is
in charge of dispatching the events to the appropriate widgets and this
includes the drawing events.
这个主执行绪(也叫做UI执行绪)非常重要,
因为它用来调度事件给适合的元件也包含绘制使用者介面的事件。
It is also the thread you interact with Android widgets on.
它也是那个你与Android互动的widget所在的执行绪。
For instance, if you touch the a button on screen, the UI thread dispatches
the touch event to the widget which in turn sets its pressed state and posts
an invalidate request to the event queue. The UI thread dequeues the request
and notifies the widget to redraw itself.
举个例子,假设你在画面上碰触一个按钮,
UI执行绪会将这个碰触事件分派给那个依序设定为「已按下」状态及
提出一个「失效」的请求(request)到事件伫列里的widget。
这个UI执行绪会从伫列取得该请求并且通知元件去重画自己。
This single thread model can yield poor performance in Android applications
that do not consider the implications.
这个单一的执行绪模型在没考虑到其影响的Android应用程式中
可能造成较差的效能。
Since everything happens on a single thread performing long operations, like
network access or database queries, on this thread will block the whole user
interface. No event can be dispatched, including drawing events, while the
long operation is underway.
如果在一个单一执行绪发生的每件事都做了很久的运算,
像是网路存取或者跟资料库要资料,这样的执行绪将会把使用者的画面锁住。
当这些长时间的运算正在进行中时,将会没有任何事件可以被触发,
包含重画画面的事件。
From the user's perspective, the application appears hung. Even worse, if the
UI thread is blocked for more than a few seconds (about 5 seconds currently)
the user is presented with the infamous "application not responding" (ANR)
dialog.
当使用者看到画面停住不动,甚至更坏的情况,
像UI执行绪占住画面约超过5秒的时间,
画面就会跳出万恶的ANR警告视窗。
If you want to see how bad this can look, write a simple application with a
button that invokes Thread.sleep(2000) in itsOnClickListener. The button will
remain in its pressed state for about 2 seconds before going back to its
normal state. When this happens, it is very easy for the user to perceive the
application as slow.
假设你想看见这样情况有多糟,写一个简单的应用程式,
上面有一个button并且按下去的事件会执行Thread.sleep(2000),
这个button将会出现被按下去的画面约2秒才会回到正常弹起来的画面,
当这样的情况发生的时候,这个程式很容易让使用者感觉『吼~有够慢』。
Now that you know you must avoid lengthy operations on the UI thread, you
will probably use extra threads (background orworker threads) to perform
these operations, and rightly so.
现在你知道你必需避免在UI执行绪上有长的运算。
你也许将使用额外的执行绪(背景处理的执行绪)来执行这些运算,
这的确是必须做的。
Let's take the example of a click listener downloading an image over the
network and displaying it in an ImageView:
让我们来看看一个例子,当执行click事件的时候,
它会从网路下载图片并且载入ImageView里面。
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork();
mImageView.setImageBitmap(b);
}
}).start();
}
At first, this code seems to be a good solution to your problem, as it does
not block the UI thread. Unfortunately, it violates the single thread model:
the Android UI toolkit is not thread-safe and must always be manipulated on
the UI thread.
首先,这段程式码似乎可以简单的解决你的问题,
它并不会占住UI执行绪,但是很不幸的
,它违反单一执行绪的模型:Android UI 工具不是thread-safe
(很多执行绪执行互相不影响),而且必须被操作在UI 执行绪上面。
In this piece of code, the ImageView is manipulated on a worker thread, which
can cause really weird problems. Tracking down and fixing such bugs can be
difficult and time-consuming.
在上面的程式码内,ImageView是执行在其他的执行绪,
它将会造成很诡异的问题,要找出这样的错误是非常困难而且耗时的。
Android offers several ways to access the UI thread from other threads. You
may already be familiar with some of them but here is a comprehensive list:
Android提供数个方法从其他的执行绪来存取UI执行绪。
以下是这些方法的完整清单,你可能已经熟悉其中的一些了。
‧ Activity.runOnUiThread(Runnable)
‧ View.post(Runnable)
‧ View.postDelayed(Runnable, long)
‧ Handler
Any of these classes and methods could be used to correct our previous code
example:
在这些类别和方法的其中之一都能用来解决我们先前范例的问题。
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap b = loadImageFromNetwork();
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(b);
}
});
}
}).start();
}
Unfortunately, these classes and methods also tend to make your code more
complicated and more difficult to read.
不幸地,这些类别跟方法也趋使你的程式码变的更复杂难以阅读。
It becomes even worse when your implement complex operations that require
frequent UI updates.
它更糟糕的是当你执行复杂的运算时,会频繁要求UI更新。
To remedy this problem, Android 1.5 offers a new utility class, called
AsyncTask, that simplifies the creation of long-running tasks that need to
communicate with the user interface.
为了解决这个问题,Android1.5提供一个新的类别叫做AsyncTask,
它简化了需要与使用者介面沟通的长时间执行任务的创建程序。
AsyncTask is also available for Android 1.0 and 1.1 under the name UserTask.
It offers the exact same API and all you have to do is copy its source code
in your application.
AsyncTask在Android1.0跟1.1也以UserTask这个名字存在着。
它提供额外相同的API而且你只需要复制原始码在你的程式里面。
The goal of AsyncTask is to take care of thread management for you. Our
previous example can easily be rewritten withAsyncTask:
AsyncTask的目的是帮你处理执行绪的管理,
我们先前的例子可以很容易地用AsyncTask重写如下:
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask {
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
As you can see, AsyncTask must be used by subclassing it. It is also very
important to remember that an AsyncTask instance has to be created on the UI
thread and can be executed only once.
如你所见,AsyncTask必须被继承,
AsyncTask实体必须被建立在UI执行绪而且只能执行一次,
这个非常的重要。
You can read the AsyncTask documentation for a full understanding on how to
use this class, but here is a quick overview of how it works:
你可以从AsyncTask的文件得到如何使用这个class的完整了解,
而这是对於它如何运作的一个快速概述。
最後,感谢Haotung学长帮忙校正。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 61.62.29.91
1F:推 stanleypipi:帮推 03/09 23:28
2F:→ james732:深蓝色实在不太好读 03/10 00:18
3F:推 nowar100:推多执行绪的概念,不过深蓝色真的不太好读 :( 03/10 03:52
那黄色呢?^^
※ 编辑: givemepass 来自: 219.84.187.88 (03/10 07:12)
4F:→ nowar100:收录至 z-2-6 03/10 08:33
5F:推 cjoe:推 03/10 09:39
6F:推 yienge:用心推 03/10 10:54
7F:推 runescape1:好文 03/10 14:04
8F:推 james732:黄色比较好了,补一个推! 03/10 22:18
9F:推 mamaya3:推荐! 03/11 05:02
10F:推 tericky:推~ 03/11 13:01
11F:推 tomap41017:推 03/11 23:24
12F:推 lovelycateye:推一下 虽然我个人偏好用Handler做 03/12 20:01
13F:推 quare96:推~ 同楼上XD 03/13 12:19
14F:推 JamesEX:感觉async task不是特别好用// 03/13 13:01