導航:首頁 > 操作系統 > android不能在主線程

android不能在主線程

發布時間:2022-09-26 05:30:57

① 為什麼說android主線程是線程不安全的,既然不安全為什麼要在主線程中更新UI,有點暈 求大師解答

UI線程及Android的單線程模型原則當應用啟動,系統會創建一個主線程(main thread)。這個主線程負責向UI組件分發事件(包括繪制事件),也是在這個主線程里,應用和Android的UI組件(components from the Android UI toolkit (components from the android.widget and android.view packages))發生交互。

當App做一些比較重(intensive)的工作的時候,除非合理地實現,否則單線程模型的performance會很poor。特別的是,如果所有的工作都在UI線程,做一些比較耗時的工作比如訪問網路或者資料庫查詢,都會阻塞UI線程,導致事件停止分發(包括繪制事件)。對於用戶來說,應用看起來像是卡住了,更壞的情況是,如果UI線程blocked的時間太長(大約超過5秒),用戶就會看到ANR(application not responding)的對話框。

另外,Andoid UI toolkit並不是線程安全的,所以不能從非UI線程來操縱UI組件。必須把所有的UI操作放在UI線程里,所以Android的單線程模型有兩條原則:
1.不要阻塞UI線程。
2.不要在UI線程之外訪問Android UI toolkit(主要是這兩個包中的組件:android.widget and android.view)。

② Android:在一個非主線程內直接調用UI線程的Handler實例,這樣沒問題嗎

我們開發應用程序的時候,處於線程安全的原因子線程通常是不能直接更新主線程(UI線程)中的UI元素的,那麼在Android開發中有幾種方法解決這個問題,其中方法之一就是利用Handler處理的。

下面說下有關Handler相關的知識。
多線程一些基礎知識回顧:
在介紹Handler類相關知識之前,我們先看看在Java中是如何創建多線程的
方法有兩種:
通過繼承Thread類,重寫Run方法來實現
通過繼承介面Runnable實現多線程

接下來讓我們看看Handler是什麼?如何來用

Handler是這么定義的:
主要接受子線程發送的數據, 並用此數據配合主線程更新UI.

Handler的主要作用:主要用於非同步消息的處理

Handler的運行過程:
當(子線程)發出一個消息之後,首先進入一個(主線程的)消息隊列,發送消息的函數即刻返回,而在主線程中的Handler逐個的在消息隊列中將消息取出,然後對消息進行處理。這樣就實現了跨線程的UI更新(實際上還是在主線程中完成的)。
這種機制通常用來處理相對耗時比較長的操作,如訪問網路比較耗時的操作,讀取文大文件,比較耗時的操作處理等。

在大白話一點的介紹它的運行過程:
啟動應用時Android開啟一個主線程 (也就是UI線程) , 如果此時需要一個耗時的操作,例如: 聯網讀取數據,或者讀取本地較大的一個文件的時候,你不能把這些操作放在主線程中,如果你放在主線程中的話,界面會出現假死現象(這也就是你在主線程中直接訪問網路時會提示你異常的原因,如我們上篇文章所述Android主線程不能訪問網路異常解決辦法
)。
這個時候我們需要把這些耗時的操作,放在一個子線程中,因為子線程涉及到UI更新,Android主線程是線程不安全的,更新UI只能在主線程中更新.。
這個時候,Handler就出現了,來解決這個復雜的問題,由於Handler運行在主線程中(UI線程中), 它與子線程可以通過Message對象來傳遞數據, 這個時候,Handler就承擔著接受子線程傳過來的(子線程用sedMessage()方法傳弟)Message對象,(裡麵包含數據) , 把這些消息放入主線程隊列中,配合主線程進行更新UI。

接下來我們看看關於Handler都有哪些方法(它都能幹什麼):
其中Handler對象的一些主要方法,如下:

post(Runnable) postAtTime(Runnable,long)

postDelayed(Runnable long)

sendEmptyMessage(int)

sendMessage(Message)

sendMessageAtTime(Message,long)

sendMessageDelayed(Message,long)

正如方法名字中看到的,有兩類方法:

(1)在某個主線程中執行Runnable
(2)在子線程中發送一個消息,在主線程中檢測該消息處理

線程間傳遞Message對象的sendMessage方法和發送Runnable多線程對象的post方法。正對應著上面所說的兩個特性1)、2)

下面開發個Handler實例做說明:
用post的方法執行一個Runnable對象,在該對象中隨機產生一個10-100之間的隨機數,賦值到UI主線程中的TextView中線程,執行5次,每次相隔5秒, 拼接每次的數字, 最後執行結果應該如:10 22 33 44 61

主要代碼如下:
int i = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler.post(run);
}

Handler handler = new Handler(){
@Override
public void handleMessage(Message msg){
String s = String.valueOf(msg.what);
TextView tv = (TextView)findViewById(R.id.textView);
tv.setText(tv.getText() + 」 」 + s);
}
};

Runnable run = new Runnable(){
@Override
public void run(){
Random r = new Random();
int rnum = r.nextInt((100 – 10) + 1) + 10;
handler.sendEmptyMessage(rnum);
handler.postDelayed(run, 5000);
i++;
if (i==5){
handler.removeCallbacks(run);
}
}
};

③ android 怎麼執行主線程

可以。你這個問題是,android 能不能在 非主activity的 類B中,調用activity A的方法。
在B做一個activity的 變數。在B構造函數中 對context參數 保存,記得要對context 強制轉換類型 變為主線程的 activity。之後在B中就能靠activity變數調用 A的方法。
不過你這個是多線程,要用synchronize做好共享數據保護工作。

④ 每個Android 都應必須了解的多線程知識點~

進程是系統調度和資源分配的一個獨立單位。

在Android中,一個應用程序就是一個獨立的集成,應用運行在一個獨立的環境中,可以避免其他應用程序/進程的干擾。當我們啟動一個應用程序時,系統就會創建一個進程(該進程是從Zygote中fork出來的,有獨立的ID),接著為這個進程創建一個主線程,然後就可以運行MainActivity了,應用程序的組件默認都是運行在其進程中。開發者可以通過設置應用的組件的運行進程,在清單文件中給組件設置:android:process = "進程名";可以達到讓組件運行在不同進程中的目的。讓組件運行在不同的進程中,既有好處,也有壞處。我們依次的說明下。

好處:每一個應用程序(也就是每一個進程)都會有一個內存預算,所有運行在這個進程中的程序使用的總內存不能超過這個值,讓組件運行不同的進程中,可以讓主進程可以擁有更多的空間資源。當我們的應用程序比較大,需要的內存資源比較多時(也就是用戶會抱怨應用經常出現OutOfMemory時),可以考慮使用多進程。

壞處:每個進程都會有自己的虛擬機實例,因此讓在進程間共享一些數據變得相對困難,需要採用進程間的通信來實現數據的共享。

線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。

在Android中,線程會有那麼幾種狀態:創建、就緒、運行、阻塞、結束。當應用程序有組件在運行時,UI線程是處於運行狀態的。默認情況下,應用的所有組件的操作都是在UI線程里完成的,包括響應用戶的操作(觸摸,點擊等),組件生命周期方法的調用,UI的更新等。因此如果UI線程處理阻塞狀態時(在線程里做一些耗時的操作,如網路連接等),就會不能響應各種操作,如果阻塞時間達到5秒,就會讓程序處於ANR(application not response)狀態。

1.線程作用

減少程序在並發執行時所付出的時空開銷,提高操作系統的並發性能。

2.線程分類

守護線程、非守護線程(用戶線程)

2.1 守護線程

定義:守護用戶線程的線程,即在程序運行時為其他線程提供一種通用服務
常見:如垃圾回收線程
設置方式:thread.setDaemon(true);//設置該線程為守護線程

2.2 非守護線程(用戶線程)

主線程 & 子線程。

2.2.1 主線程(UI線程)

定義:Android系統在程序啟動時會自動啟動一條主線程
作用:處理四大組件與用戶進行交互的事情(如UI、界面交互相關)
因為用戶隨時會與界面發生交互,因此主線程任何時候都必須保持很高的響應速度,所以主線程不允許進行耗時操作,否則會出現ANR。

2.2.2 子線程(工作線程)

定義:手動創建的線程
作用:耗時的操作(網路請求、I/O操作等)

2.3 守護線程與非守護線程的區別和聯系

區別:虛擬機是否已退出,即
a. 當所有用戶線程結束時,因為沒有守護的必要,所以守護線程也會終止,虛擬機也同樣退出
b. 反過來,只要任何用戶線程還在運行,守護線程就不會終止,虛擬機就不會退出

3.線程優先順序

3.1 表示

線程優先順序分為10個級別,分別用Thread類常量表示。

3.2 設置

通過方法setPriority(int grade)進行優先順序設置,默認線程優先順序是5,即 Thread.NORM_PRIORITY。

4.線程狀態

創建狀態:當用 new 操作符創建一個線程的時候

就緒狀態:調用 start 方法,處於就緒狀態的線程並不一定馬上就會執行 run 方法,還需要等待CPU的調度

運行狀態:CPU 開始調度線程,並開始執行 run 方法

阻塞(掛起)狀態:線程的執行過程中由於一些原因進入阻塞狀態,比如:調用 sleep/wait 方法、嘗試去得到一個鎖等

結束(消亡)狀態:run 方法執行完 或者 執行過程中遇到了一個異常

(1)start()和run()的區別

通過調用Thread類的start()方法來啟動一個線程,這時此線程是處於就緒狀態,並沒有運行。調用Thread類調用run()方法來完成其運行操作的,方法run()稱為線程體,它包含了要執行的這個線程的內容,run()運行結束,此線程終止,然後CPU再調度其它線程。

(2)sleep()、wait()、yield()的區別

sleep()方法屬於Thread類,wait()方法屬於Object類。
調用sleep()方法,線程不會釋放對象鎖,只是暫停執行指定的時間,會自動恢復運行狀態;調用wait()方法,線程會放棄對象鎖,進入等待此對象的等待鎖定池,不調用notify()方法,線程永遠處於就緒(掛起)狀態。

yield()直接由運行狀態跳回就緒狀態,表示退讓線程,讓出CPU,讓CPU調度器重新調度。禮讓可能成功,也可能不成功,也就是說,回到調度器和其他線程進行公平競爭。

1.Android線程的原則

(1)為什麼不能再主線程中做耗時操作
防止ANR, 不能在UI主線程中做耗時的操作,因此我們可以把耗時的操作放在另一個工作線程中去做。操作完成後,再通知UI主線程做出相應的響應。這就需要掌握線程間通信的方式了。 在Android中提供了兩種線程間的通信方式:一種是AsyncTask機制,另一種是Handler機制。

(2)為什麼不能在非UI線程中更新UI 因為Android的UI線程是非線程安全的,應用更新UI,是調用invalidate()方法來實現界面的重繪,而invalidate()方法是非線程安全的,也就是說當我們在非UI線程來更新UI時,可能會有其他的線程或UI線程也在更新UI,這就會導致界面更新的不同步。因此我們不能在非UI主線程中做更新UI的操作。

2.Android實現多線程的幾種方式

3.為何需要多線程

多線程的本質就是非同步處理,直觀一點說就是不要讓用戶感覺到「很卡」。

4.多線程機制的核心是啥

多線程核心機制是Handler

推薦Handler講解視頻: 面試總被問到Handler?帶你從源碼的角度解讀Handler核心機制

根據上方提到的 多進程、多線程、Handler 問題,我整理了一套 Binder與Handler 機制解析的學習文檔,提供給大家進行學習參考,有需要的可以 點擊這里直接獲取!!! 裡面記錄許多Android 相關學習知識點。

⑤ android訪問網路狀態是否可在主線程中執行

是的,android2.2版本以下是可以在主線程中執行網路訪問的,2.2以上就得重起一個線程了。

⑥ android toast必須在主線程嗎

不能,Toast只能在 主線程 (UI線程)中使用

⑦ android代碼,我無論如何也無法在主線程中等待dialog的出現

自己看看書把,在子線程中發消息出來,然後在主線程接受到消息的時候彈出dialog

⑧ android中 IO操作可以放在主線程么。為什麼

Android的io操作就是需要放在主線程中,不過這個操作的過程最好放在其他的線程,這樣子才不會是屏幕出現卡頓。如果你直接放在其他線程就會導致出錯,android這么規定的

閱讀全文

與android不能在主線程相關的資料

熱點內容
java是不是數字 瀏覽:180
php模擬瀏覽器環境 瀏覽:351
編程誰都能學會嗎 瀏覽:407
使用國家反詐app都要開啟什麼 瀏覽:712
下載民宿APP有什麼用 瀏覽:50
續子語pdf 瀏覽:385
2021年加密貨幣最新行情 瀏覽:162
nfs怎麼加密ipsec 瀏覽:245
國二考試調用編譯器運算選擇題 瀏覽:750
同濟大學高等數學pdf 瀏覽:234
延時的宏命令怎麼設置 瀏覽:596
資料庫有哪些加密 瀏覽:209
改之理反編譯注冊教程 瀏覽:391
什麼是編譯程序和翻譯程序 瀏覽:208
python課程心得總結 瀏覽:17
派派中怎麼看對方在哪個伺服器 瀏覽:796
xp配置java環境變數配置 瀏覽:9
python中1到100怎麼算 瀏覽:768
小度我想看程序員 瀏覽:508
bs刷裝備建立後文件夾沒有 瀏覽:82