日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android线程详解

發布時間:2024/4/15 Android 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android线程详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

現在大多數的移動設備已經變得越來越快,但是它們其實也不算是非常快。如果你想讓你的APP既可以承受一些繁雜的工作而又不影響用戶體驗的話,那么必須把任務并行執行。在Android上,我們使用線程。

端一杯咖啡,然后仔細閱讀這篇文章。我會給大家介紹一下線程的概念,還有在Java中怎么使用線程,在線程中怎么使用Handler等。

如果需要使用異步處理或者并行任務的話,那么你一定會用到線程。

什么是線程?

線程或者線程執行本質上就是一串命令(也是程序代碼),然后我們把它發送給操作系統執行。

一般來說,我們的CPU在任何時候一個核只能處理一個線程。多核處理器(目前大多數Android設備已經都是多核)顧名思義,就是可以同時處理多線程(通俗地講就是可以同時處理多件事)。

多核處理與單核多任務處理的實質

上面我說的是一般情況,并不是所有的描述都是一定正確的。因為單核也可以用多任務模擬出多線程。

每個運行在線程中的任務都可以分解成多條指令,而且這些指令不用同時執行。所以,單核設備可以首先切換到線程1去執行指令1A,然后切換到線程2去執行指令2A,接著返回到線程1再去執行1B、1C、1D,然后繼續切換到線程2,執行2B、2C等等,以此類推。

這個線程之間的切換十分迅速,以至于在單核的設備中也會發生。幾乎所有的線程都在相同的時間內進行任務處理。其實,這都是因為速度太快造成的假象,就像電影《黑客帝國》里的特工Brown一樣,可以變幻出很多的頭和手。

接下來我們來看一些代碼。

Java核心里的線程

在Java中,如果要想做平行任務處理的話,會在Runnable里面執行你的代碼。可以繼承Thread類,或者實現Runnable接口:

// Version 1 publicclass IAmAThread extendsThread { ????publicIAmAThread() { ????????super("IAmAThread"); ????} ????@Override ????publicvoid run() { ????????// your code (sequence of instructions) ????} } // to execute this sequence of instructions in a separate thread. newIAmAThread().start(); // Version 2 publicclass IAmARunnable implementsRunnable { ????@Override ????publicvoid run() { ????????// your code (sequence of instructions) ????} } // to execute this sequence of instructions in a separate thread. IAmARunnable myRunnable = newIAmARunnable(); newThread(myRunnable).start();

這兩個方法基本上是一樣的。第一個版本是創建一個Thread類,第二個版本是需要創建一個Runnable對象,然后也需要一個Thread類來調用它。

第二個版是通常建議使用的方法。這也是一個很大的主題了,超過了本文的范圍,以后會再做討論。

Android上的線程

無論何時啟動APP,所有的組件都會運行在一個單獨的線程中(默認的)——叫做主線程。這個線程主要用于處理UI的操作并為視圖組件和小部件分發事件等,因此主線程也被稱作UI線程。

如果你在UI線程中運行一個耗時操作,那么UI就會被鎖住,直到這個耗時操作結束。對于用戶體驗來說,這是非常糟糕的!這也就是為什么我們要理解Android上的線程機制了。理解這些機制就可以把一些復雜的工作移動到其它的線程中去執行。如果你在UI線程中運行一個耗時的任務,那么很有可能會發生ANR(應用無響應),這樣用戶就會很快地結束掉你的APP。

Android和Java一樣,它支持使用Java里面的Thread類來進行一步任務處理。所以可以輕松地像上面Java的例子一樣來使用Android上的線程,不過那好像還是有點困難。

為什么在Android上使用標準Java的線程會困難呢?

其實平行任務處理沒有想象中的那么簡單,你必須在多線程中保證并發,就像偉大的Tim Bray說的那樣:ordinary humans can’t do concurrency at scale (or really at all) …

特別對于Android來說,以下這些功能就略顯臃腫:

  • 異步對于UI線程來說是一個主要的PITA(如果你需要在后臺線程中向主線程更新界面,那么你就會用到)。
  • 如果屏幕方向或者屏幕配置改變的話,就會出現一些更加奇怪的現象。因為改變屏幕方向,會引起Activity重建(所以后臺線程就需要去改變被銷毀的Activity的狀態了,而如果后臺線程不是在UI線程之上的話,那情況會更加復雜,原因如條件1)。
  • 對于線程池來說,沒有默認的處理方式。
  • 取消線程操作需要自定義代碼實現。
  • 那么在Android上怎么進行任務并發處理呢?

    你可能聽過一些Android上一些常見的名詞:

    1、Handler
    這就是我們今天要討論的詳細主題。

    2、AsyncTask
    使用AsyncTask是在Android上操作線程最簡單的方式,也是最容易出錯的方式。

    3、IntentService
    這種方式需要寫更多的代碼,但是這是把耗時任務移動到后臺的很好的方式,也是我最喜歡的方式。配上使用一個EventBus機制的框架如Otto,這樣的話實現IntentService就非常簡單了。

    4、Loader
    關于處理異步任務,還有很多事情需要做,比如從數據庫或者內容提供者那里處理一些數據。

    5、Service
    如果你曾經使用過Service的話,你應該知道這里會有一點誤區,其中一個常見的誤解就是服務是運行在后臺線程的。其實不是!看似運行在后臺是因為它們不與UI組件關聯,但是它們(默認)是運行在UI線程上的……所以默認運行在UI線程上,甚至在上面沒有UI部件。

    如果想要把服務運行在后臺線程中,那么必須自定義一個線程,然后把操作代碼都運行在那個線程中(與上面提到的方法很類似)。事實上你應該使用IntentService實現,但是這不是本文討論的主題。

    Android上的Handler

    以下是從?Android developer documentation for Handlers:中摘選的一段話:

    > A Handler allows you to send and process Message and Runnable objects associated with a thread’s MessageQueue. Each Handler instance is associated with a single thread and that thread’s message queue. When you create a new Handler, it is bound to the thread/message queue of the thread that is creating it — from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

    為了更好地了解這個概念,也許你需要去看看什么是Message Queues。

    消息隊列

    在線程里基本都有一個叫做“消息隊列”的東西,它負責線程間通信。這是一種設計模式,所有控制指令或者內容在線程間傳遞。

    消息隊列如同它的名字那樣,對于線程來說,它就是一個指令隊列。這里我們還可以做一些更酷的事:

    • 定時消息和線程在某個時間點才執行。
    • 需要在另一個線程中去添加入隊動作,而不是在本線程中。

    注意:這里說的“消息”和Runnable對象、指令隊列的概念是一樣的。

    回到Android上的Handler……如果你仔細閱讀的話,可以看到文檔是這樣說的:

    > A Handler allows you to send and process Message and Runnable objects associated with a thread’s MessageQueue.

    所以Handler可以讓你給線程隊列發消息:

    > Each Handler instance is associated with a single thread and that thread’s message queue.

    一個Handler對象只能和一個線程關聯:

    > When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it

    所以一個Handler到底和哪個線程關聯呢?就是創造它的線程。

    > — from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.、

    在我們了解這些知識后,請繼續看……

    小貼士:?這里有幾點可能你還不知道。每個線程都和一個Handler類實例綁定,而且可以和別的線程一起運行,相互通信。

    還有一個小建議(如果用過AsyncTask的話),AsyncTask內部也是使用Handler進行處理的,只是不是運行在UI線程而已,它會提供一個channel來和UI線程通信,使用postExecute方法即可實現。

    這還挺酷的,那怎么創建Handler呢?

    有兩種方式:

  • 使用默認的構造方法:new Handler()。
  • 使用帶參的構造方法,參數是一個Runnable對象或者回調對象。
  • Handler里面有什么實用的API嗎?

    請記住:

    • Handler只是簡單往消息隊列中發送消息而已(或者使用post方式)
    • 它們有更方便的方法可以幫助與UI線程通信。

    如果你現在看看Handler的API,可以清楚看到這幾個方法:

  • post
  • postDelayed
  • postAtTime
  • 代碼示例

    這里的代碼都是很基礎的,不過你可以好好看看注釋。

    示例1:使用Handler的“post”方法

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 publicclass TestActivity extendsActivity { // ... // all standard stuff @Override publicvoid onCreate(Bundle savedInstanceState) { ????// ... ????// all standard stuff ????// we're creating a new handler here ????// and we're in the UI Thread (default) ????// so this Handler is associated with the UI thread ????Handler mHandler = newHandler(); ????// I want to start doing something really long ????// which means I should run the fella in another thread. ????// I do that by sending a message - in the form of another runnable object ????// But first, I'm going to create a Runnable object or a message for this ????Runnable mRunnableOnSeparateThread = newRunnable() { ????????@Override ????????publicvoid run () { ????????????// do some long operation ????????????longOperation(); ????????????// After mRunnableOnSeparateThread is done with it's job, ????????????// I need to tell the user that i'm done ????????????// which means I need to send a message back to the UI thread ????????????// who do we know that's associated with the UI thread? ????????????mHandler.post(newRunnable(){ ????????????????@Override ????????????????publicvoid run(){ ????????????????????// do some UI related thing ????????????????????// like update a progress bar or TextView ????????????????????// .... ????????????????} ????????????}); ????????} ????}; ????// Cool but I've not executed the mRunnableOnSeparateThread yet ????// I've only defined the message to be sent ????// When I execute it though, I want it to be in a different thread ????// that was the whole point. ????newThread(mRunnableOnSeparateThread).start(); } }

    如果根本就沒有Handler對象,回調post方法會比較難辦。

    示例2:使用postDelayed方法

    近期本站新介紹的特性中,我每次都要模擬EditText的自動完成功能,每次文字改變后都會觸發一個API的調用,從服務器中檢索數據。

    我想減少APP調用API的次數,所以決定使用Handler的postDelayed方法來實現這個功能。

    本例不針對平行處理,只是關于Handler給消息隊列發送消息還有安排消息在未來的某一點執行等。

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 // the below code is inside a TextWatcher // which implements the onTextChanged method // I've simplified it to only highlight the parts we're // interested in privatelong lastChange = 0; @Override publicvoid onTextChanged(finalCharSequence chars, ??????????????????????????intstart, intbefore, intcount) { ????????// The handler is spawned from the UI thread ????????newHandler().postDelayed( ????????????// argument 1 for postDelated = message to be sent ????????????newRunnable() { ????????????????@Override ????????????????publicvoid run() { ????????????????????if(noChangeInText_InTheLastFewSeconds()) { ????????????????????????searchAndPopulateListView(chars.toString());?// logic ????????????????????} ????????????????} ????????????}, ????????????// argument 2 for postDelated = delay before execution ????????????300); ????????lastChange = System.currentTimeMillis(); } privateboolean noChangeInText_InTheLastFewSeconds() { ????returnSystem.currentTimeMillis() - lastChange >= 300 }

    最后我就把“postAtTime”這個方法作為聯系留給讀者們了,掌握Handler了嗎?如果是的話,那么可以盡情使用線程了。


    1. Android進程

    ?? ?在了解Android線程之前得先了解一下Android的進程。當一個程序第一次啟動的時候,Android會啟動一個LINUX進程和一個主線程。默認的情況下,所有該程序的組件都將在該進程和線程中運行。同時,Android會為每個應用程序分配一個單獨的LINUX用戶。Android會盡量保留一個正在運行進程,只在內存資源出現不足時,Android會嘗試停止一些進程從而釋放足夠的資源給其他新的進程使用, 也能保證用戶正在訪問的當前進程有足夠的資源去及時地響應用戶的事件。Android會根據進程中運行的組件類別以及組件的狀態來判斷該進程的重要性,Android會首先停止那些不重要的進程。按照重要性從高到低一共有五個級別:

    • 前臺進程
      前臺進程是用戶當前正在使用的進程。只有一些前臺進程可以在任何時候都存在。他們是最后一個被結束的,當內存低到根本連他們都不能運行的時候。一般來說, 在這種情況下,設備會進行內存調度,中止一些前臺進程來保持對用戶交互的響應。
    • 可見進程
      可見進程不包含前臺的組件但是會在屏幕上顯示一個可見的進程是的重要程度很高,除非前臺進程需要獲取它的資源,不然不會被中止。
    • 服務進程
      運行著一個通過startService() 方法啟動的service,這個service不屬于上面提到的2種更高重要性的。service所在的進程雖然對用戶不是直接可見的,但是他們執行了用戶非常關注的任務(比如播放mp3,從網絡下載數據)。只要前臺進程和可見進程有足夠的內存,系統不會回收他們。
    • 后臺進程
      運行著一個對用戶不可見的activity(調用過 onStop() 方法).這些進程對用戶體驗沒有直接的影響,可以在服務進程、可見進程、前臺進 程需要內存的時候回收。通常,系統中會有很多不可見進程在運行,他們被保存在LRU (least recently used) 列表中,以便內存不足的時候被第一時間回收。如果一個activity正 確的執行了它的生命周期,關閉這個進程對于用戶體驗沒有太大的影響。
    • 空進程
      未運行任何程序組件。運行這些進程的唯一原因是作為一個緩存,縮短下次程序需要重新使用的啟動時間。系統經常中止這些進程,這樣可以調節程序緩存和系統緩存的平衡。

    ?? ?Android 對進程的重要性評級的時候,選取它最高的級別。另外,當被另外的一個進程依賴的時候,某個進程的級別可能會增高。一個為其他進程服務的進程永遠不會比被服務的進程重要級低。因為服務進程比后臺activity進程重要級高,因此一個要進行耗時工作的activity最好啟動一個service來做這個工作,而不是開啟一個子進程――特別是這個操作需要的時間比activity存在的時間還要長的時候。例如,在后臺播放音樂,向網上上傳攝像頭拍到的圖片,使用service可以使進程最少獲取到“服務進程”級別的重要級,而不用考慮activity目前是什么狀態。broadcast receivers做費時的工作的時候,也應該啟用一個服務而不是開一個線程。

    2. 單線程模型

    ?? ?當一個程序第一次啟動時,Android會同時啟動一個對應的主線程(Main Thread),主線程主要負責處理與UI相關的事件,如用戶的按鍵事件,用戶接觸屏幕的事件以及屏幕繪圖事件,并把相關的事件分發到對應的組件進行處理。所以主線程通常又被叫做UI線程在開發Android應用時必須遵守單線程模型的原則: Android UI操作并不是線程安全的并且這些操作必須在UI線程中執行。

    2.1 子線程更新UI

    ?? ?Android的UI是單線程(Single-threaded)的。為了避免拖住GUI,一些較費時的對象應該交給獨立的線程去執行。如果幕后的線程來執行UI對象,Android就會發出錯誤訊息?CalledFromWrongThreadException。以后遇到這樣的異常拋出時就要知道怎么回事了!

    2.2 Message Queue

    ?? ??在單線程模型下,為了解決類似的問題,Android設計了一個Message Queue(消息隊列), 線程間可以通過該Message Queue并結合Handler和Looper組件進行信息交換。下面將對它們進行分別介紹:

    1. Message Message消息,理解為線程間交流的信息,處理數據后臺線程需要更新UI,則發送Message內含一些數據給UI線程。 2. Handler Handler處理者,是Message的主要處理者,負責Message的發送,Message內容的執行處理。后臺線程就是通過傳進來的Handler對象引用來sendMessage(Message)。而使用Handler,需要implement 該類的?handleMessage(Message)方法,它是處理這些Message的操作內容,例如Update UI。通常需要子類化Handler來實現handleMessage方法。 3. Message Queue Message Queue消息隊列,用來存放通過Handler發布的消息,按照先進先出執行。 每個message queue都會有一個對應的Handler。Handler會向message queue通過兩種方法發送消息:sendMessage或post。這兩種消息都會插在message queue隊尾并按先進先出執行。但通過這兩種方法發送的消息執行的方式略有不同:通過sendMessage發送的是一個message對象,會被Handler的handleMessage()函數處理;而通過post方法發送的是一個runnable對象,則會自己執行。 4. Looper Looper是每條線程里的Message Queue的管家。Android沒有Global的Message Queue,而Android會自動替主線程(UI線程)建立Message Queue,但在子線程里并沒有建立Message Queue。所以調用Looper.getMainLooper()得到的主線程的Looper不為NULL,但調用Looper.myLooper()得到當前線程的Looper就有可能為NULL。

    ?? ?對于子線程使用Looper,API Doc提供了正確的使用方法:

  • class?LooperThread?extends?Thread?{?
  • ????public?Handler?mHandler;?
  • ?
  • ????public?void?run()?{?
  • ????????Looper.prepare();?//創建本線程的Looper并創建一個MessageQueue
  • ?
  • ????????mHandler?=?new?Handler()?{?
  • ????????????public?void?handleMessage(Message?msg)?{?
  • ????????????????//?process?incoming?messages?here?
  • ????????????}?
  • ????????};?
  • ???
  • ????????Looper.loop();?//開始運行Looper,監聽Message?Queue?
  • ????}?
  • }?
  • ?? ?這個Message機制的大概流程:

    ?? ?1. 在Looper.loop()方法運行開始后,循環地按照接收順序取出Message Queue里面的非NULL的Message。

    ?? ?2. 一開始Message Queue里面的Message都是NULL的。當Handler.sendMessage(Message)到Message Queue,該函數里面設置了那個Message對象的target屬性是當前的Handler對象。隨后Looper取出了那個Message,則調用該Message的target指向的Hander的dispatchMessage函數對Message進行處理。

    ?? ?在dispatchMessage方法里,如何處理Message則由用戶指定,三個判斷,優先級從高到低:

    ?? ?1) Message里面的Callback,一個實現了Runnable接口的對象,其中run函數做處理工作;

    ?? ?2) Handler里面的mCallback指向的一個實現了Callback接口的對象,由其handleMessage進行處理;

    ?? ?3) 處理消息Handler對象對應的類繼承并實現了其中handleMessage函數,通過這個實現的handleMessage函數處理消息。

    ?? ?由此可見,我們實現的handleMessage方法是優先級最低的!

    ?? ?3. Handler處理完該Message (update UI) 后,Looper則設置該Message為NULL,以便回收!

    ?? ?在網上有很多文章講述主線程和其他子線程如何交互,傳送信息,最終誰來執行處理信息之類的,個人理解是最簡單的方法——判斷Handler對象里面的Looper對象是屬于哪條線程的,則由該線程來執行! ?? ?1. 當Handler對象的構造函數的參數為空,則為當前所在線程的Looper; ?? ?2.?Looper.getMainLooper()得到的是主線程的Looper對象,Looper.myLooper()得到的是當前線程的Looper對象。

    現在來看一個例子,模擬從網絡獲取數據,加載到ListView的過程:

  • public?class?ListProgressDemo?extends?ListActivity?{?
  • ?
  • ????@Override?
  • ????public?void?onCreate(Bundle?savedInstanceState)?{?
  • ????????super.onCreate(savedInstanceState);?
  • ????????setContentView(R.layout.listprogress);?
  • ?
  • ????????((Button)?findViewById(R.id.load_Handler)).setOnClickListener(new?View.OnClickListener(){?
  • ?
  • ????????????@Override?
  • ????????????public?void?onClick(View?view)?{?
  • ????????????????data?=?null;?
  • ????????????????data?=?new?ArrayList<String>();?
  • ?
  • ????????????????adapter?=?null;?
  • ?
  • ????????????????showDialog(PROGRESS_DIALOG);?
  • ????????????????new?ProgressThread(handler,?data).start();?
  • ????????????}?
  • ????????});?
  • ????}?
  • ?
  • ????@Override?
  • ????protected?Dialog?onCreateDialog(int?id)?{?
  • ????????switch(id)?{?
  • ????????case?PROGRESS_DIALOG:?
  • ?????????????????return?ProgressDialog.show(this,?"",??
  • ???????????????????"Loading.?Please?wait...",?true);?
  • ?
  • ????????default:?return?null;?
  • ????????}?
  • ????}?
  • ?
  • ????private?class?ProgressThread?extends?Thread?{?
  • ?
  • ????????private?Handler?handler;?
  • ????????private?ArrayList<String>?data;?
  • ?
  • ????????public?ProgressThread(Handler?handler,?ArrayList<String>?data)?{?
  • ????????????this.handler?=?handler;?
  • ????????????this.data?=?data;?
  • ????????}?
  • ?
  • ????????@Override?
  • ????????public?void?run()?{?
  • ????????????for?(int?i=0;?i<8;?i++)?{?
  • ????????????????data.add("ListItem");?//后臺數據處理
  • ????????????????try?{?
  • ????????????????????Thread.sleep(100);?
  • ????????????????}catch(InterruptedException?e)?{?
  • ?????????????????????
  • ????????????????????Message?msg?=?handler.obtainMessage();?
  • ????????????????????Bundle?b?=?new?Bundle();?
  • ????????????????????b.putInt("state",?STATE_ERROR);?
  • ????????????????????msg.setData(b);?
  • ????????????????????handler.sendMessage(msg);??
  • ?????????????????????
  • ????????????????}?
  • ????????????}?
  • ????????????Message?msg?=?handler.obtainMessage();?
  • ????????????Bundle?b?=?new?Bundle();?
  • ????????????b.putInt("state",?STATE_FINISH);?
  • ????????????msg.setData(b);?
  • ????????????handler.sendMessage(msg);?
  • ????????}?
  • ?????????
  • ????}?
  • ?
  • ????//?此處甚至可以不需要設置Looper,因為Handler默認就使用當前線程的Looper
  • ????private?final?Handler?handler?=?new?Handler(Looper.getMainLooper())?{
  • ?
  • ????????public?void?handleMessage(Message?msg)?{?// 處理Message,更新ListView
  • ????????????int?state?=?msg.getData().getInt("state");?
  • ????????????switch(state){?
  • ????????????????case?STATE_FINISH:?
  • ????????????????????dismissDialog(PROGRESS_DIALOG);?
  • ????????????????????Toast.makeText(getApplicationContext(),?
  • ????????????????????????????"加載完成!",?
  • ????????????????????????????Toast.LENGTH_LONG)?
  • ?????????????????????????.show();?
  • ?
  • ????????????????????adapter?=?new?ArrayAdapter<String>(getApplicationContext(),?
  • ????????????????????????????android.R.layout.simple_list_item_1,?
  • ????????????????????????????data?);?
  • ?????????????????????????????
  • ????????????????????setListAdapter(adapter);?
  • ?
  • ????????????????????break;?
  • ?
  • ????????????????case?STATE_ERROR:?
  • ???????????????????dismissDialog(PROGRESS_DIALOG);?
  • ???????????????????Toast.makeText(getApplicationContext(),?
  • ???????????????????????????"處理過程發生錯誤!",?
  • ???????????????????????????Toast.LENGTH_LONG)?
  • ????????????????????????.show();?
  • ?
  • ???????????????????adapter?=?new?ArrayAdapter<String>(getApplicationContext(),?
  • ???????????????????????????android.R.layout.simple_list_item_1,?
  • ???????????????????????????data?);?
  • ????????????????????????????
  • ??????????????????????setListAdapter(adapter);?
  • ?
  • ??????????????????????break;?
  • ?
  • ???????????????default:?
  • ?
  • ????????????}?
  • ????????}?
  • ????};?
  • ?
  • ?
  • ????private?ArrayAdapter<String>?adapter;?
  • ????private?ArrayList<String>?data;?
  • ?
  • ????private?static?final?int?PROGRESS_DIALOG?=?1;?
  • ????private?static?final?int?STATE_FINISH?=?1;?
  • ????private?static?final?int?STATE_ERROR?=?-1;?
  • }?
  • 這個例子,我自己寫完后覺得還是有點亂,要稍微整理才能看明白線程間交互的過程以及數據的前后變化。隨后了解到AsyncTask類,相應修改后就很容易明白了!

    2.3 AsyncTask

    AsyncTask版:
  • ((Button)?findViewById(R.id.load_AsyncTask)).setOnClickListener(new?View.OnClickListener(){?
  • ?
  • ????@Override?
  • ????public?void?onClick(View?view)?{?
  • ????????data?=?null;?
  • ????????data?=?new?ArrayList<String>();?
  • ?
  • ????????adapter?=?null;?
  • ?
  • ????????//顯示ProgressDialog放到AsyncTask.onPreExecute()里?
  • ????????//showDialog(PROGRESS_DIALOG);?
  • ????????new?ProgressTask().execute(data);?
  • ????}?
  • });?
  • ?
  • private?class?ProgressTask?extends?AsyncTask<ArrayList<String>,?Void,?Integer>?{?
  • ?
  • /*?該方法將在執行實際的后臺操作前被UI?thread調用。可以在該方法中做一些準備工作,如在界面上顯示一個進度條。*/?
  • @Override?
  • protected?void?onPreExecute()?{?
  • ????//?先顯示ProgressDialog
  • ????showDialog(PROGRESS_DIALOG);?
  • }?
  • ?
  • /*?執行那些很耗時的后臺計算工作。可以調用publishProgress方法來更新實時的任務進度。?*/?
  • @Override?
  • protected?Integer?doInBackground(ArrayList<String>...?datas)?{?
  • ????ArrayList<String>?data?=?datas[0];?
  • ????for?(int?i=0;?i<8;?i++)?{?
  • ????????data.add("ListItem");?
  • ????}?
  • ????return?STATE_FINISH;?
  • }?
  • ?
  • /*?在doInBackground?執行完成后,onPostExecute?方法將被UI?thread調用,?
  • ?*?后臺的計算結果將通過該方法傳遞到UI?thread.?
  • ?*/?
  • @Override?
  • protected?void?onPostExecute(Integer?result)?{?
  • ????int?state?=?result.intValue();?
  • ????switch(state){?
  • ????case?STATE_FINISH:?
  • ????????dismissDialog(PROGRESS_DIALOG);?
  • ????????Toast.makeText(getApplicationContext(),?
  • ????????????????"加載完成!",?
  • ????????????????Toast.LENGTH_LONG)?
  • ?????????????.show();?
  • ?
  • ????????adapter?=?new?ArrayAdapter<String>(getApplicationContext(),?
  • ????????????????android.R.layout.simple_list_item_1,?
  • ????????????????data?);?
  • ?????????????????
  • ????????setListAdapter(adapter);?
  • ?
  • ????????break;?
  • ?????????
  • ????case?STATE_ERROR:?
  • ???????dismissDialog(PROGRESS_DIALOG);?
  • ???????Toast.makeText(getApplicationContext(),?
  • ???????????????"處理過程發生錯誤!",?
  • ???????????????Toast.LENGTH_LONG)?
  • ????????????.show();
  • ?
  • ???????adapter?=?new?ArrayAdapter<String>(getApplicationContext(),?
  • ???????????????android.R.layout.simple_list_item_1,?
  • ???????????????data?);
  • ?
  • ??????????setListAdapter(adapter);
  • ?
  • ??????????break;
  • ?
  • ???default:
  • ?
  • ???}
  • }
  • ?? ?Android另外提供了一個工具類:AsyncTask。它使得UI thread的使用變得異常簡單。它使創建需要與用戶界面交互的長時間運行的任務變得更簡單,不需要借助線程和Handler即可實現。

    1) ?子類化AsyncTask 2) ?實現AsyncTask中定義的下面一個或幾個方法 onPreExecute() 開始執行前的準備工作; doInBackground(Params...) 開始執行后臺處理,可以調用publishProgress方法來更新實時的任務進度; onProgressUpdate(Progress...) ?在publishProgress方法被調用后,UI thread將調用這個方法從而在界面上展示任務的進展情況,例如通過一個進度條進行展示。 onPostExecute(Result) 執行完成后的操作,傳送結果給UI 線程。 這4個方法都不能手動調用。而且除了doInBackground(Params...)方法,其余3個方法都是被UI線程所調用的,所以要求: 1) AsyncTask的實例必須在UI thread中創建; 2) AsyncTask.execute方法必須在UI thread中調用; 同時要注意:該task只能被執行一次,否則多次調用時將會出現異常。而且是不能手動停止的,這一點要注意,看是否符合你的需求! 在使用過程中,發現AsyncTask的構造函數的參數設置需要看明白:AsyncTask<Params, Progress, Result> Params對應doInBackground(Params...)的參數類型。而new AsyncTask().execute(Params... params),就是傳進來的Params數據,你可以execute(data)來傳送一個數據,或者execute(data1, data2, data3)這樣多個數據。 Progress對應onProgressUpdate(Progress...)的參數類型; Result對應onPostExecute(Result)的參數類型。 當以上的參數類型都不需要指明某個時,則使用Void,注意不是void。不明白的可以參考上面的例子,或者API Doc里面的例子。 ---------------- 本文的相當內容摘錄于《淺析Android線程模型一 --- 轉》,但對于Message機制的流程理解則在參考《android中Message機制的靈活應用》后修改了!

    轉自:http://blog.jobbole.com/73267/ ?

    ? ? ? ? ? ?http://android.blog.51cto.com/268543/343823

    與50位技術專家面對面20年技術見證,附贈技術全景圖

    總結

    以上是生活随笔為你收集整理的Android线程详解的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。