Looper.prepare()和Looper.loop()

来源:http://www.cnblogs.com/l2rf/archive/2016/11/11/6055218.html
-Advertisement-
Play Games

什麼時候需要 Looper Looper用於封裝了android線程中的消息迴圈,預設情況下一個線程是不存在消息迴圈(message loop)的,需要調用Looper.prepare()來給線程創建一個消息迴圈,調用Looper.loop()來使消息迴圈起作用,使用Looper.prepare() ...


 

什麼時候需要 Looper

  Looper用於封裝了android線程中的消息迴圈,預設情況下一個線程是不存在消息迴圈(message loop)的,需要調用Looper.prepare()來給線程創建一個消息迴圈,調用Looper.loop()來使消息迴圈起作用,使用Looper.prepare()和Looper.loop()創建了消息隊列就可以讓消息處理在該線程中完成。

 

使用Looper需要註意什麼

  寫在Looper.loop()之後的代碼不會被立即執行,當調用後mHandler.getLooper().quit()後,loop才會中止,其後的代碼才能得以運行。Looper對象通過MessageQueue來存放消息和事件。一個線程只能有一個Looper,對應一個MessageQueue。

比如下麵的代碼,只要調用了getLooper().quit()後代碼2才會執行。

 1 class LooperThread extends Thread
 2 {
 3     4     public void run() 
 5     {
 6         Looper.prepare();
 7          //代碼1....
 8         Looper.loop();
 9         //代碼2....
10     }    
11 }        

 

警惕線程未終止造成的記憶體泄露;譬如在Activity中關聯了一個生命周期超過Activity的Thread,在退出Activity時切記結束線程。一個典型的例子就是HandlerThread的run方法是一個死迴圈,它不會自己結束,線程的生命周期超過了Activity生命周期,我們必須手動在Activity的銷毀方法中中調運thread.getLooper().quit();才不會泄露。

 

 

Looper與Activity

Activity的MainUI線程預設是有消息隊列的。所以在Activity中新建Handler時,不需要先調用Looper.prepare()

 

主線程中的Looper.loop()一直無限迴圈為什麼不會造成ANR

ActivityThread.java 是主線程入口的類,這裡你可以看到寫Java程式中司空見慣的main方法,而main方法正是整個Java程式的入口。

 

ActivityThread源碼

1 public static final void main(String[] args) {
2         ...
3         //創建Looper和MessageQueue
4         Looper.prepareMainLooper();
5         ...
6         //輪詢器開始輪詢
7         Looper.loop();
8         ...
9     }

Looper.loop()方法

1  while (true) {
2        //取出消息隊列的消息,可能會阻塞
3        Message msg = queue.next(); // might block
4        ...
5        //解析消息,分發消息
6        msg.target.dispatchMessage(msg);
7        ...
8     }

ActivityThread的main方法主要就是做消息迴圈,一旦退出消息迴圈,那麼你的應用也就退出了。那為什麼這個死迴圈不會造成ANR異常呢?

因為Android 的是由事件驅動的,looper.loop() 不斷地接收事件、處理事件,每一個點擊觸摸或者說Activity的生命周期都是運行在 Looper.loop() 的控制之下,如果它停止了,應用也就停止了。只能是某一個消息或者說對消息的處理阻塞了 Looper.loop(),而不是 Looper.loop() 阻塞它。也就說我們的代碼其實就是在這個迴圈裡面去執行的,當然不會阻塞了。


handleMessage方法部分源碼

 1 public void handleMessage(Message msg) {
 2         if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
 3         switch (msg.what) {
 4             case LAUNCH_ACTIVITY: {
 5                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
 6                 final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
 7                 r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
 8                 handleLaunchActivity(r, null);
 9                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
10             }
11             break;
12             case RELAUNCH_ACTIVITY: {
13                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
14                 ActivityClientRecord r = (ActivityClientRecord) msg.obj;
15                 handleRelaunchActivity(r);
16                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
17             }
18             break;
19             case PAUSE_ACTIVITY:
20                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
21                 handlePauseActivity((IBinder) msg.obj, false, (msg.arg1 & 1) != 0, msg.arg2, (msg.arg1 & 2) != 0);
22                 maybeSnapshot();
23                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
24                 break;
25             case PAUSE_ACTIVITY_FINISHING:
26                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
27                 handlePauseActivity((IBinder) msg.obj, true, (msg.arg1 & 1) != 0, msg.arg2, (msg.arg1 & 1) != 0);
28                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
29                 break;
30             ...........
31         }
32     }

可以看見Activity的生命周期都是依靠主線程的Looper.loop,當收到不同Message時則採用相應措施。

如果某個消息處理時間過長,比如你在onCreate(),onResume()裡面處理耗時操作,那麼下一次的消息比如用戶的點擊事件不能處理了,整個迴圈就會產生卡頓,時間一長就成了ANR。



引用:http://www.jianshu.com/p/cfe50b8b0a41  

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 關於egret接入第三方庫的方法,egret也有文檔,可參考官方的接入方法接入http://developer.egret.com/cn/github/egret-docs/extension/threes/instructions/index.html。 這裡記錄一下接入puremvc庫的過程,關 ...
  • 在複習廖雪峰老師的JS教程時,看到數組,又遇到了之前做過的那道小題,題目如下: 練習:在新生歡迎會上,你已經拿到了新同學的名單,請排序後顯示:歡迎XXX,XXX,XXX和XXX同學!: 給出了數組: 這道題作為一個練習並不是很難,當時自己第一次看也是按照最直接的辦法,使用了${arr[i]}來拿到對 ...
  • Redux就是個數據中心,不依附於任何框架在哪使用都行。但是和它最搭配的應該就是React了,而且大家學習它的動力大多也是解決React狀態管理的問題。都說Redux文檔詳盡清晰,但我感覺並不友好,它沒有用最簡單直觀的方式告訴你如何搭配React使用。研究了兩天的文檔和示例,終於在項目中用上了我認為 ...
  • 目前 "AlloyFinger" 作為騰訊手機QQ web手勢解決方案,在各大項目中都發揮著作用。 感興趣的同學可以去Github看看: "https://github.com/AlloyTeam/AlloyFinger" 在騰訊,如:興趣部落、QQ群、QQ動漫、騰訊學院、TEDxTencent、 ...
  • 1、跨域請求: Cross Domain Request:跨功能變數名稱的HTTP請求,瀏覽器從某個功能變數名稱下的資源訪問了另一功能變數名稱下的另一資源(協議、功能變數名稱或是埠號不同); ①瀏覽器允許跨域請求的情形: <img>、<link>、<script>、<iframe> ②禁止跨域請求的情形: XHR——瀏覽器預設出 ...
  • 前言 DOM的作用是將網頁轉為一個javascript對象,從而可以使用javascript對網頁進行各種操作(比如增刪內容)。瀏覽器會根據DOM模型,將HTML文檔解析成一系列的節點,再由這些節點組成一個樹狀結構。DOM的最小組成單位叫做節點(node),文檔的樹形結構(DOM樹)由12種類型的節 ...
  • 簡介 沒有用過Node,記的這些只是學習的筆記,有什麼錯的地方,望各位前輩指正。 Node是一個伺服器端Javascript解釋器,依賴於Chrome v8引擎進行代碼編譯,事件驅動、非阻塞I/O都是他顯著的特點。 伺服器能夠處理的併發連接的最大數量是目前Web應用程式架構的瓶頸,Node的出現就打 ...
  • 一、項目概要 1.1 項目效果如圖: 1.2 需要使用到的技術 ViewDragHelper: 要實現和QQ5.0側滑的特效,需要藉助谷歌在2013年I/O大會上發佈的ViewDragHelper類,提供這個類目的就是為瞭解決拖拽滑動問題 1.3 側滑菜單的實現方式 1. SlidingMenu 第 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...