自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

切記!不要在UI主線程中進(jìn)行耗時(shí)的操作

移動(dòng)開發(fā) Android
這是一個(gè)很棒的問題,畢竟開發(fā)者總是希望基于舊版本系統(tǒng)開發(fā)的應(yīng)用在新版本的Android系統(tǒng)仍能兼容。在我看來,問題的原因可能多種多樣。 但大多數(shù)時(shí)候,原因非常簡(jiǎn)單:你把一個(gè)可能非常耗時(shí)的操作放進(jìn)了UI線程。

問題

自Android Ice Cream Sandwich發(fā)布后, 這個(gè)問題就開始在StackOverflow彌散開來:

我的應(yīng)用在Android2.x上運(yùn)行良好,但是在3.x 和4.x系統(tǒng)上總是強(qiáng)退,是什么導(dǎo)致的?

這是一個(gè)很棒的問題,畢竟開發(fā)者總是希望基于舊版本系統(tǒng)開發(fā)的應(yīng)用在新版本的Android系統(tǒng)仍能兼容。在我看來,問題的原因可能多種多樣。 但大多數(shù)時(shí)候,原因非常簡(jiǎn)單:你把一個(gè)可能非常耗時(shí)的操作放進(jìn)了UI線程。

 

什么是UI線程?

 

應(yīng)用的主UI線程的概念及其重要性是每個(gè)Android開發(fā)者都應(yīng)理解。當(dāng)一個(gè)應(yīng)用啟動(dòng),系統(tǒng)會(huì)為應(yīng)用創(chuàng)建一個(gè)名為“main”的主線程。這個(gè)主線程(也就是UI主線程)主要負(fù)責(zé)把事件分發(fā)給合適的view或者widget, 因此它非常重要。它也是你的應(yīng)用和應(yīng)用的UI交互的線程。例如,如果你點(diǎn)擊了屏幕上的一個(gè)按鈕,UI線程會(huì)把點(diǎn)擊時(shí)間交給view處理,view接到事件后會(huì)設(shè)置它的pressed狀態(tài),然后向事件隊(duì)列中發(fā)送一個(gè)invalidate請(qǐng)求。 UI線程會(huì)依次讀取隊(duì)列并且告訴view去重繪自己。

除非你的Android應(yīng)用實(shí)現(xiàn)的非常合理,否則這個(gè)單線程模型會(huì)使性能變得極低。在極端情況下,如果UI線程負(fù)責(zé)整個(gè)應(yīng)用中的所有操作,進(jìn)行耗時(shí)的操作比如發(fā)送網(wǎng)絡(luò)請(qǐng)求,或者數(shù)據(jù)庫查詢等都會(huì)導(dǎo)致用戶界面的阻塞。這些操作在未完成之前,所有的時(shí)間包括繪制和觸屏事件都不會(huì)被派發(fā)。從用戶的角度來看,程序似乎是卡死了。

在這些情況下,即時(shí)的反饋相當(dāng)重要。研究表明0.1s是用戶感覺系統(tǒng)是否流暢的臨界值。任何比臨界值更慢的都被認(rèn)為延遲(Miller 1968; Card et al. 1991)。雖然1秒看起來沒什么影響,但在GooglePlay中,即便是十分之一秒也可能是好評(píng)和差評(píng)的區(qū)別。更糟糕的是,如果UI線程被阻塞5秒以上,用戶會(huì)收到“程序未響應(yīng)”(ANR)的提示對(duì)話框,并且會(huì)強(qiáng)制退出。

 

為什么Android會(huì)使應(yīng)用崩潰

 

應(yīng)用在2.x系統(tǒng)運(yùn)行良好,在3.0及以上平臺(tái)上崩潰的主要原因在于,3.0以上平臺(tái)在處理UI線程資源濫用上更加嚴(yán)格。比如說,3.0平臺(tái)檢測(cè)到UI線程中有網(wǎng)絡(luò)請(qǐng)求時(shí),會(huì)拋出NetworkOnMainThreadExceptionwill的異常:

E/AndroidRuntime(673): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example/com.example.ExampleActivity}: android.os.NetworkOnMainThreadException

Android developer網(wǎng)站文檔中也對(duì)此進(jìn)行了很好的解釋:

當(dāng)應(yīng)用試圖在主線程中進(jìn)行網(wǎng)絡(luò)操作,NetworkOnMainThreadException會(huì)被拋出。只有在運(yùn)行Honeycomb SDK及更高的版本中會(huì)被拋出。更早版本的SDK允許在主事件循環(huán)線程中進(jìn)行網(wǎng)絡(luò)操作,但是非常非常不鼓勵(lì)這么做。

列出一些ICS和Honeycomb不允許在UI線程中進(jìn)行的操作:

打開套接字連接 (i.e. new Socket()).

 

HTTP 請(qǐng)求 (i.e. HTTPClient and HTTPUrlConnection).

 

試圖連接遠(yuǎn)程的 MYSQL 數(shù)據(jù)庫.

 

下載文件 (i.e.Downloader.downloadFile()).

 

如果你要在UI線程中進(jìn)行某些操作,一定要把它們打包到一個(gè)工作線程中。其中最簡(jiǎn)單的方式是使用AsyncTask, 它允許你在你的用戶界面中進(jìn)行一些異步的操作。AsyncTask會(huì)把阻塞操作放到工作線程中,并把結(jié)果返回到UI線程,而你不需要處理任何與線程相關(guān)的工作。

 

結(jié)論

 

我決定寫這篇主題的念頭來源于我在StackOerflow和其它論壇上無數(shù)次看到了這個(gè)問題。問題的主要來源是在UI線程進(jìn)行了耗時(shí)的操作。為了確保用戶界面保持流暢,有必要把執(zhí)行套接字連接、HTTP請(qǐng)求、文件下載和其他的耗時(shí)操作放到一個(gè)單獨(dú)的線程中。最簡(jiǎn)單的方法就是把操作打包到AsyncTask中,它會(huì)幫助你啟動(dòng)新的線程并讓他們與你的用戶界面異步交互。

 

有幫助的鏈接

 

這些資料可能會(huì)幫助你熟悉AsyncTask

AsyncTask documentation

 

Multithreading For Performance

 

責(zé)任編輯:chenqingxiang
相關(guān)推薦

2017-03-13 10:41:33

iOSUI操作主線程

2023-03-17 16:42:45

應(yīng)用開發(fā)Ability

2012-03-28 22:06:15

Android

2017-01-03 17:57:46

Android異步精髓Handler

2010-02-01 17:33:24

Python主線程

2010-02-02 16:47:12

Python主線程

2024-04-15 12:27:00

await面試接口

2025-04-11 11:55:49

2016-10-21 13:03:18

androidhandlerlooper

2023-01-17 17:45:28

UI界面多線程

2010-02-26 15:37:11

Python主線程

2010-03-10 19:34:45

Python主線程

2015-10-10 10:36:00

warning category

2021-10-20 14:53:31

Foreach強(qiáng)制阿里巴巴

2013-04-12 10:05:20

Android多線程后臺(tái)運(yùn)行操作

2021-08-12 16:28:10

AndroidHandleLooper

2011-01-19 12:52:49

WCF.NETC#

2023-09-27 10:19:37

類型video函數(shù)

2024-10-07 08:28:03

WPFUI應(yīng)用程序

2021-01-13 09:07:32

MySQLOrderLimit
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)