[分享] Painless threading (翻譯版)

看板AndroidDev作者 (〆)時間13年前 (2011/03/09 23:21), 編輯推噓12(1202)
留言14則, 12人參與, 最新討論串1/1
最近執行緒有一些問題,因此找了一些資料, 剛好看到這一篇文章,因為是原文的,想說翻譯起來可以讓有需要的人參考, 如果翻錯或者不是那麼正確,請千萬一定要讓我知道,避免誤導大家,謝謝。 原文連結 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

03/09 23:28, , 1F
幫推
03/09 23:28, 1F

03/10 00:18, , 2F
深藍色實在不太好讀
03/10 00:18, 2F

03/10 03:52, , 3F
推多執行緒的概念,不過深藍色真的不太好讀 :(
03/10 03:52, 3F
那黃色呢?^^ ※ 編輯: givemepass 來自: 219.84.187.88 (03/10 07:12)

03/10 08:33, , 4F
收錄至 z-2-6
03/10 08:33, 4F

03/10 09:39, , 5F
03/10 09:39, 5F

03/10 10:54, , 6F
用心推
03/10 10:54, 6F

03/10 14:04, , 7F
好文
03/10 14:04, 7F

03/10 22:18, , 8F
黃色比較好了,補一個推!
03/10 22:18, 8F

03/11 05:02, , 9F
推薦!
03/11 05:02, 9F

03/11 13:01, , 10F
推~
03/11 13:01, 10F

03/11 23:24, , 11F
03/11 23:24, 11F

03/12 20:01, , 12F
推一下 雖然我個人偏好用Handler做
03/12 20:01, 12F

03/13 12:19, , 13F
推~ 同樓上XD
03/13 12:19, 13F

03/13 13:01, , 14F
感覺async task不是特別好用//
03/13 13:01, 14F
文章代碼(AID): #1DTvi2zd (AndroidDev)
文章代碼(AID): #1DTvi2zd (AndroidDev)