最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android多線程學(xué)習(xí)實(shí)例詳解

 更新時(shí)間:2016年10月26日 10:58:20   作者:Wallace  
這篇文章主要介紹了Android多線程,結(jié)合實(shí)例形式較為詳細(xì)的分析了Android多線程的概念、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下

本文實(shí)例分析了Android多線程。分享給大家供大家參考,具體如下:

在Android下面也有多線程的概念,在C/C++中,子線程可以是一個(gè)函數(shù),一般都是一個(gè)帶有循環(huán)的函數(shù),來處理某些數(shù)據(jù),優(yōu)先線程只是一個(gè)復(fù) 雜的運(yùn)算過程,所以可能不需要while循環(huán),運(yùn)算完成,函數(shù)結(jié)束,線程就銷毀。對于那些需要控制的線程,一般我們都是和互斥鎖相互關(guān)聯(lián),從而來控制線程 的進(jìn)度,一般我們創(chuàng)建子線程,一種線程是很常見的,那就是帶有消息循環(huán)的線程。

消息循環(huán)是一個(gè)很有用的線程方式,曾經(jīng)自己用C在Linux下面實(shí)現(xiàn)一個(gè)消息循環(huán)的機(jī)制,往消息隊(duì)列里添加數(shù)據(jù),然后異步的等待消息的返回。當(dāng)消息隊(duì)列為空的時(shí)候就會掛起線程,等待新的消息的加入。這是一個(gè)很通用的機(jī)制。

在Android,這里的線程分為有消息循環(huán)的線程和沒有消息循環(huán)的線程,有消息循環(huán)的線程一般都會有一個(gè)Looper,這個(gè)事android的新 概念。我們的主線程(UI線程)就是一個(gè)消息循環(huán)的線程。針對這種消息循環(huán)的機(jī)制,我們引入一個(gè)新的機(jī)制Handle,我們有消息循環(huán),就要往消息循環(huán)里 面發(fā)送相應(yīng)的消息,自定義消息一般都會有自己對應(yīng)的處理,消息的發(fā)送和清除,消息的的處理,把這些都封裝在Handle里面,注意Handle只是針對那 些有Looper的線程,不管是UI線程還是子線程,只要你有Looper,我就可以往你的消息隊(duì)列里面添加?xùn)|西,并做相應(yīng)的處理。

但是這里還有一點(diǎn),就是只要是關(guān)于UI相關(guān)的東西,就不能放在子線程中,因?yàn)樽泳€程是不能操作UI的,只能進(jìn)行數(shù)據(jù)、系統(tǒng)等其他非UI的操作。

那么什么情況下面我們的子線程才能看做是一個(gè)有Looper的線程呢?我們?nèi)绾蔚玫剿麹ooper的句柄呢?

Looper.myLooper();獲得當(dāng)前的Looper

Looper.getMainLooper () 獲得UI線程的Lopper

我們看看Handle的初始化函數(shù),如果沒有參數(shù),那么他就默認(rèn)使用的是當(dāng)前的Looper,如果有Looper參數(shù),就是用對應(yīng)的線程的Looper。

如果一個(gè)線程中調(diào)用Looper.prepare(),那么系統(tǒng)就會自動的為該線程建立一個(gè)消息隊(duì)列,然后調(diào)用 Looper.loop();之后就進(jìn)入了消息循環(huán),這個(gè)之后就可以發(fā)消息、取消息、和處理消息。這個(gè)如何發(fā)送消息和如何處理消息可以再其他的線程中通過 Handle來做,但前提是我們的Hanle知道這個(gè)子線程的Looper,但是你如果不是在子線程運(yùn)行 Looper.myLooper(),一般是得不到子線程的looper的。

public void run() {
  synchronized (mLock) {
    Looper.prepare();
    //do something
  }
  Looper.loop();
}

所以很多人都是這樣做的:我直接在子線程中新建handle,然后在子線程中發(fā)送消息,這樣的話就失去了我們多線程的意義了。

class myThread extends Thread{
   private EHandler mHandler ;
   public void run() {
     Looper myLooper, mainLooper;
     myLooper = Looper.myLooper ();
    mainLooper = Looper.getMainLooper ();
    String obj;
    if (myLooper == null ){
         mHandler = new EHandler(mainLooper);
         obj = "current thread has no looper!" ;
    }
    else {
       mHandler = new EHandler(myLooper);
       obj = "This is from current thread." ;
    }
    mHandler .removeMessages(0);
    Message m = mHandler .obtainMessage(1, 1, 1, obj);
    mHandler .sendMessage(m);
   }
}

可以讓其他的線程來控制我們的handle,可以把 private EHandler mHandler ;放在外面,這樣我們的發(fā)消息和處理消息都可以在外面來定義,這樣增加程序代碼的美觀,結(jié)構(gòu)更加清晰。

對如任何的Handle,里面必須要重載一個(gè)函數(shù)

public void handleMessage(Message msg)

這個(gè)函數(shù)就是我們的消息處理,如何處理,這里完全取決于你,然后通過 obtainMessage和 sendMessage等來生成和發(fā)送消息, removeMessages(0)來清除消息隊(duì)列。Google真是太智慧了,這種框架的產(chǎn)生,我們寫代碼更加輕松了。

有的時(shí)候,我們的子線程想去改變UI了,這個(gè)時(shí)候千萬不要再子線程中去修改,獲得UI線程的Looper,然后發(fā)送消息即可。

我們來看看高煥堂的代碼:

// class ac01 extends Activity {
 // ………
   public void onClick(View v) {
       switch (v.getId()){
       case 101:
             t = new myThread();
          t .start();
         break ;
       case 102:
     finish();
            break ;
       }
  }
//------------------------------------------------------
class EHandler extends Handler {
      public EHandler(Looper looper) {
        super (looper);
      }
      @Override
      public void handleMessage(Message msg) {
       tv .setText((String)msg. obj );
    }
  }
//------------------------------------------------------
class myThread extends Thread{
   private EHandler mHandler ;
   public void run() {
    Looper myLooper, mainLooper;
    myLooper = Looper.myLooper ();
    mainLooper = Looper.getMainLooper ();
    String obj;
    if (myLooper == null ){
        mHandler = new EHandler(mainLooper);
        obj = "current thread has no looper!" ;
    }
    else {
       mHandler = new EHandler(myLooper);
       obj = "This is from current thread." ;
    }
    mHandler .removeMessages(0);
    Message m = mHandler .obtainMessage(1, 1, 1, obj);
    mHandler .sendMessage(m);
   }
 }
}

完全是不知所云,一坨狗屎。我們來看,在上面的run里面

Looper myLooper, mainLooper;
myLooper = Looper.myLooper (); //很明顯這個(gè)會返回空,因?yàn)槟氵€沒有 prepare,不會返回Looper。
mainLooper = Looper.getMainLooper ();

建議大家在看Looper的時(shí)候不要看高煥堂的書,感覺他也不是很懂,倒還把我搞糊涂了。講了那么多,完全是他自己的理解,他自己的理解很是復(fù)雜,關(guān)鍵的是把簡單的問題復(fù)雜化,并且復(fù)雜之后的東西還是錯(cuò)的。我們看看Goole Music App的源代碼。

在MediaPlaybackActivity.java中,我們可以看一下再OnCreate中的有這樣的兩句:

mAlbumArtWorker = new Worker("album art worker");
mAlbumArtHandler = new AlbumArtHandler(mAlbumArtWorker.getLooper());

很明顯這兩句,是構(gòu)建了一個(gè)子線程。并且這個(gè)子線程還是Looper的子線程,這里很牛逼的使用了 mAlbumArtWorker.getLooper()這個(gè)函數(shù),因?yàn)槲覀冎溃覀兡軌虻玫阶泳€程的Looper的途徑只有一個(gè):就是在子線程中調(diào)用 Looper.myLooper (),并且這個(gè)函數(shù)還要在我們perpare之后調(diào)用才能得到正確的Looper,但是他這里用了一個(gè)這樣的什么東東 getLooper,不知道它是如何實(shí)現(xiàn)的?

這里有一個(gè)大概的思路,我們在子線程的的prepare之后調(diào)用 myLooper ()這個(gè)方法,然后保存在一個(gè)成員變量中,這個(gè)getLooper就返回這個(gè)東西,但是這里會碰到多線程的一個(gè)很突出的問題,同步。我們在父線程中調(diào)用 mAlbumArtWorker.getLooper(),但是想要這個(gè)返回正確的looper就必須要求我們的子線程運(yùn)行了prepare,但是這個(gè)東 西實(shí)在子線程運(yùn)行的,我們?nèi)绾伪WC呢?

我們看Google是如何實(shí)現(xiàn)的?

private class Worker implements Runnable {
    private final Object mLock = new Object();
    private Looper mLooper;
    /**
     * Creates a worker thread with the given name. The thread
     * then runs a {@link android.os.Looper}.
     * @param name A name for the new thread
     */
    Worker(String name) {
      Thread t = new Thread(null, this, name);
      t.setPriority(Thread.MIN_PRIORITY);
      t.start();
      synchronized (mLock) {
        while (mLooper == null) {
          try {
            mLock.wait();
          } catch (InterruptedException ex) {
          }
        }
      }
    }
    public Looper getLooper() {
      return mLooper;
    }
    public void run() {
      synchronized (mLock) {
        Looper.prepare();
        mLooper = Looper.myLooper();
        mLock.notifyAll();
      }
      Looper.loop();
    }
    public void quit() {
      mLooper.quit();
    }
}

我們知道,一個(gè)線程類的構(gòu)造函數(shù)是在主線程中完成的,所以在我們的 Worker的構(gòu)造函數(shù)中我們創(chuàng)佳一個(gè)線程,然后讓這個(gè)線程運(yùn)行,這一這個(gè)線程的創(chuàng)建是指定一個(gè) Runnabl,這里就是我們的Worker本身,在主線程調(diào)用 t.start();,這后,我們子線程已經(jīng)創(chuàng)建,并且開始執(zhí)行work的run方法。然后下面的代碼很藝術(shù):

synchronized (mLock) {
    while (mLooper == null) {
      try {
        mLock.wait();
      } catch (InterruptedException ex) {
      }
    }
}

我們開始等待我們的子線程給mLooper賦值,如果不賦值我們就繼續(xù)等,然后我們的子線程在運(yùn)行run方法之后,在給 mLooper賦值之后,通知worker夠著函數(shù)中的wait,然后我們的構(gòu)造函數(shù)才能完成,所以我們說:

mAlbumArtWorker = new Worker("album art worker");

這句本身就是阻塞的,它創(chuàng)建了一個(gè)子線程,開啟了子線程,并且等待子線程給mLooper賦值,賦值完成之后,這個(gè)函數(shù)才返回,這樣才能保證我們的子線程的Looper的獲取絕對是正確的,這個(gè)構(gòu)思很有創(chuàng)意。值得借鑒。

更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android線程與消息機(jī)制用法總結(jié)》、《Android開發(fā)入門與進(jìn)階教程》、《Android調(diào)試技巧與常見問題解決方法匯總》、《Android多媒體操作技巧匯總(音頻,視頻,錄音等)》、《Android基本組件用法總結(jié)》、《Android視圖View技巧總結(jié)》、《Android布局layout技巧總結(jié)》及《Android控件用法總結(jié)

希望本文所述對大家Android程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • gradle配置國內(nèi)鏡像的實(shí)現(xiàn)

    gradle配置國內(nèi)鏡像的實(shí)現(xiàn)

    這篇文章主要介紹了gradle配置國內(nèi)鏡像的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Android使用ftp方式實(shí)現(xiàn)文件上傳和下載功能

    Android使用ftp方式實(shí)現(xiàn)文件上傳和下載功能

    這篇文章主要介紹了Android使用ftp方式實(shí)現(xiàn)文件上傳和下載功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Android 重寫ViewGroup 分析onMeasure()和onLayout()方法

    Android 重寫ViewGroup 分析onMeasure()和onLayout()方法

    這篇文章主要介紹了Android 重寫ViewGroup 分析onMeasure()和onLayout()方法的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Android之利用EventBus發(fā)送消息傳遞示例

    Android之利用EventBus發(fā)送消息傳遞示例

    本篇文章主要介紹了Android之利用EventBus進(jìn)行消息傳遞示例。EventBus是一款針對Android優(yōu)化的發(fā)布/訂閱事件總線,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。
    2017-02-02
  • Android 手勢 正則匹配圖片實(shí)例代碼

    Android 手勢 正則匹配圖片實(shí)例代碼

    這篇文章主要介紹了Android 手勢 正則匹配圖片實(shí)例代碼,需要的朋友可以參考下
    2017-07-07
  • 淺談關(guān)于Android路由的實(shí)現(xiàn)

    淺談關(guān)于Android路由的實(shí)現(xiàn)

    本篇文章主要介紹了淺談關(guān)于Android路由的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • Android如何添加控件監(jiān)聽器(三種方式)

    Android如何添加控件監(jiān)聽器(三種方式)

    本文主要介紹了Android如何添加控件監(jiān)聽器(三種方式),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Android webview手動校驗(yàn)https證書(by 星空武哥)

    Android webview手動校驗(yàn)https證書(by 星空武哥)

    有些時(shí)候由于Android系統(tǒng)的bug或者其他的原因,導(dǎo)致我們的webview不能驗(yàn)證通過我們的https證書,最明顯的例子就是華為手機(jī)mate7升級到Android7.0后,手機(jī)有些網(wǎng)站打不開了,而更新了webview的補(bǔ)丁后就沒問題了
    2017-09-09
  • Android實(shí)現(xiàn)APP自動更新功能

    Android實(shí)現(xiàn)APP自動更新功能

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)APP自動更新功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • Activity生命周期與啟動模式圖文解說

    Activity生命周期與啟動模式圖文解說

    這篇文章主要介紹了Activity生命周期與啟動模式圖文解說,內(nèi)容比較詳細(xì),具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11

最新評論

封丘县| 灌云县| 林西县| 荆州市| 新民市| 永新县| 松潘县| 宜春市| 周宁县| 广河县| 淳安县| 山东| 常山县| 青川县| 隆回县| 类乌齐县| 全州县| 奉新县| 西丰县| 错那县| 安仁县| 偃师市| 桦川县| 安吉县| 宁武县| 枣庄市| 卢龙县| 镇原县| 乐安县| 广西| 泸溪县| 左权县| 炉霍县| 综艺| 大竹县| 体育| 莒南县| 六枝特区| 嘉定区| 曲阜市| 河间市|