1. android開發中不同的activity是否在同一個線程
首先activity是android的四大組件之一,我們看到的APP界面其實就是activity,所以activity是運行在主線程中的
其次service跟activity一樣,也是android的四大組件之一,主要實現不需要界面,在後台執行的耗時操作,但是他和activity一樣,運行在同一個進程,如果結束當前activity所在進程,service也同樣會結束,因此他們兩個是運行在同一個進程中的,但不是同一個線程,service是用來處理耗時操作的,而且不需要界面支持,既然是耗時操作,就需要放在子線程中了,所以說service和activity需要在不同的線程中
解決方法,如果想讓service運行在不同線程中可以使用Thread,也可以使用handle,使service運行在中的耗時操作運行在子線程中
或者在Manifest文件中為service設置android:process,如下圖,此時service是運行在「包名+:remote」進程裡面,注意:此時service和activity是在不同的進程裡面,當然,此時的activity結束後,也不會影響到service
我們還可以使用intentservice這個抽象類,我們可以繼承實現它裡面的方法,intentservice是直接運行在子線程裡面的,可以直接在這里實現耗時操作
2. android 主線程和子線程有什麼區別
具體如下:
在一個Android 程序開始運行的時候,會單獨啟動一個Process。默認的情況下,所有這個程序中的Activity或者Service(Service和 Activity只是Android提供的Components中的兩種,除此之外還有Content Provider和Broadcast Receiver)都會跑在這個Process。
一個Android 程序默認情況下也只有一個Process,但一個Process下卻可以有許多個Thread。在這么多Thread當中,有一個Thread,我們稱之為UI Thread。UI Thread在Android程序運行的時候就被創建,是一個Process當中的主線程Main Thread,主要是負責控制UI界面的顯示、更新和控制項交互。在Android程序創建之初,一個Process呈現的是單線程模型,所有的任務都在一個線程中運行。因此,我們認為,UI Thread所執行的每一個函數,所花費的時間都應該是越短越好。而其他比較費時的工作(訪問網路,下載數據,查詢資料庫等),都應該交由子線程去執行,以免阻塞主線程。
那麼,UI Thread如何和其他Thread一起工作呢?常用方法是:誕生一個主線程的Handler物件,當做Listener去讓子線程能將訊息Push到主線程的Message Quene里,以便觸發主線程的handlerMessage()函數,讓主線程知道子線程的狀態,並在主線程更新UI。
例如,在子線程的狀態發生變化時,我們需要更新UI。如果在子線程中直接更新UI,通常會拋出下面的異常:
11-07 13:33:04.393: ERROR/JavaBinder(1029):android.view.ViewRoot$:Only the original thread that created a view hierarchy can touch its views.
意思是,無法在子線程中更新UI。為此,我們需要通過Handler物件,通知主線程Ui Thread來更新界面。
3. Android中service和子線程的用處比較
比如:程序的進程關了 service還在運行 但線程沒有 。當你要做個在APP沒運行的情況下 還能給你各種提示(消息推送什麼的)就可以開個服務
網路下載圖片什麼的 就開個線程 因為耗時的程序段是不能阻塞到ui線程(主線程)的
4. android中的service和開啟service的組件是否處於同一線程
需要說明Service也是運行在主線程的,如果Service有長時間操作,依然會阻塞主線程,造成響應超時被強制關閉。
另外,啟動服務是可以在子線程啟動的,也可以在主線程啟動,但是不管怎麼樣,服務都是運行在主線程。
綜上所述:如果啟動service在主線程,則與服務處於同一個線程,如果服務啟動在子線程,則服務不在同一線程。
5. Android開發,怎麼在service中實現 oncreat方法創建子線程,onstart里實現子線程邏輯
創建線程後,在run, while(true){ xxx()} xxx(){ if(?)xxxx ?=false} ,onstart(){? = true}
這樣能否行.. 要不然你就每次都重新創建線程發送socket..
6. Android 中的「子線程」解析
Android 中線程可分為 主線程 和 子線程 兩類,其中主線程也就是 UI線程 ,它的主要這作用就是運行四大組件、處理界面交互。子線程則主要是處理耗時任務,也是我們要重點分析的。
首先 Java 中的各種線程在 Android 里是通用的,Android 特有的線程形態也是基於 Java 的實現的,所以有必要先簡單的了解下 Java 中的線程,本文主要包括以下內容:
在 Java 中要創建子線程可以直接繼承 Thread 類,重寫 run() 方法:
或者實現 Runnable 介面,然後用Thread執行Runnable,這種方式比較常用:
簡單的總結下:
Callable 和 Runnable 類似,都可以用來處理具體的耗時任務邏輯的,但是但具體的差別在哪裡呢?看一個小例子:
定義 MyCallable 實現了 Callable 介面,和之前 Runnable 的 run() 方法對比下, call() 方法是有返回值的哦,泛型就是返回值的類型:
一般會通過線程池來執行 Callable (線程池相關內容後邊會講到),執行結果就是一個 Future 對象:
可以看到,通過線程池執行 MyCallable 對象返回了一個 Future 對象,取出執行結果。
Future 是一個介面,從其內部的方法可以看出它提供了取消任務(有坑!!!)、判斷任務是否完成、獲取任務結果的功能:
Future 介面有一個 FutureTask 實現類,同時 FutureTask 也實現了 Runnable 介面,並提供了兩個構造函數:
用 FutureTask 一個參數的構造函數來改造下上邊的例子:
FutureTask 內部有一個 done() 方法,代表 Callable 中的任務已經結束,可以用來獲取執行結果:
所以 Future + Callable 的組合可以更方便的獲取子線程任務的執行結果,更好的控制任務的執行,主要的用法先說這么多了,其實 AsyncTask 內部也是類似的實現!
注意, Future 並不能取消掉運行中的任務,這點在後邊的 AsyncTask 解析中有提到。
Java 中線程池的具體的實現類是 ThreadPoolExecutor ,繼承了 Executor 介面,這些線程池在 Android 中也是通用的。使用線程池的好處:
常用的構造函數如下:
一個常規線程池可以按照如下方式來實現:
執行任務:
基於 ThreadPoolExecutor ,系統擴展了幾類具有新特性的線程池:
線程池可以通過 execute() 、 submit() 方法開始執行任務,主要差別從方法的聲明就可以看出,由於 submit() 有返回值,可以方便得到任務的執行結果:
要關閉線程池可以使用如下方法:
IntentService 是 Android 中一種特殊的 Service,可用於執行後台耗時任務,任務結束時會自動停止,由於屬於系統的四大組件之一,相比一般線程具有較高的優先順序,不容易被殺死。用法和普通 Service 基本一致,只需要在 onHandleIntent() 中處理耗時任務即可:
至於 HandlerThread,它是 IntentService 內部實現的重要部分,細節內容會在 IntentService 源碼中說到。
IntentService 首次創建被啟動的時候其生命周期方法 onCreate() 會先被調用,所以我們從這個方法開始分析:
這里出現了 HandlerThread 和 ServiceHandler 兩個類,先搞明白它們的作用,以便後續的分析。
首先看 HandlerThread 的核心實現:
首先它繼承了 Thread 類,可以當做子線程來使用,並在 run() 方法中創建了一個消息循環系統、開啟消息循環。
ServiceHandler 是 IntentService 的內部類,繼承了 Handler,具體內容後續分析:
現在回過頭來看 onCreate() 方法主要是一些初始化的操作, 首先創建了一個 thread 對象,並啟動線程,然後用其內部的 Looper 對象 創建一個 mServiceHandler 對象,將子線程的 Looper 和 ServiceHandler 建立了綁定關系,這樣就可以使用 mServiceHandler 將消息發送到子線程去處理了。
生命周期方法 onStartCommand() 方法會在 IntentService 每次被啟動時調用,一般會這里處理啟動 IntentService 傳遞 Intent 解析攜帶的數據:
又調用了 start() 方法:
就是用 mServiceHandler 發送了一條包含 startId 和 intent 的消息,消息的發送還是在主線程進行的,接下來消息的接收、處理就是在子線程進行的:
當接收到消息時,通過 onHandleIntent() 方法在子線程處理 intent 對象, onHandleIntent() 方法執行結束後,通過 stopSelf(msg.arg1) 等待所有消息處理完畢後終止服務。
為什麼消息的處理是在子線程呢?這里涉及到 Handler 的內部消息機制,簡單的說,因為 ServiceHandler 使用的 Looper 對象就是在 HandlerThread 這個子線程類里創建的,並通過 Looper.loop() 開啟消息循環,不斷從消息隊列(單鏈表)中取出消息,並執行,截取 loop() 的部分源碼:
dispatchMessage() 方法間接會調用 handleMessage() 方法,所以最終 onHandleIntent() 就在子線程中劃線執行了,即 HandlerThread 的 run() 方法。
這就是 IntentService 實現的核心,通過 HandlerThread + Hanlder 把啟動 IntentService 的 Intent 從主線程切換到子線程,實現讓 Service 可以處理耗時任務的功能!
AsyncTask 是 Android 中輕量級的非同步任務抽象類,它的內部主要由線程池以及 Handler 實現,在線程池中執行耗時任務並把結果通過 Handler 機制中轉到主線程以實現UI操作。典型的用法如下:
從 Android3.0 開始,AsyncTask 默認是串列執行的:
如果需要並行執行可以這么做:
AsyncTask 的源碼不多,還是比較容易理解的。根據上邊的用法,可以從 execute() 方法開始我們的分析:
看到 @MainThread 註解了嗎?所以 execute() 方法需要在主線程執行哦!
進而又調用了 executeOnExecutor() :
可以看到,當任務正在執行或者已經完成,如果又被執行會拋出異常!回調方法 onPreExecute() 最先被執行了。
傳入的 sDefaultExecutor 參數,是一個自定義的串列線程池對象,所有任務在該線程池中排隊執行:
可以看到 SerialExecutor 線程池僅用於任務的排隊, THREAD_POOL_EXECUTOR 線程池才是用於執行真正的任務,就是我們線程池部分講到的 ThreadPoolExecutor :
再回到 executeOnExecutor() 方法中,那麼 exec.execute(mFuture) 就是觸發線程池開始執行任務的操作了。
那 executeOnExecutor() 方法中的 mWorker 是什麼? mFuture 是什麼?答案在 AsyncTask 的構造函數中:
原來 mWorker 是一個 Callable 對象, mFuture 是一個 FutureTask 對象,繼承了 Runnable 介面。所以 mWorker 的 call() 方法會在 mFuture 的 run() 方法中執行,所以 mWorker 的 call() 方法在線程池得到執行!
同時 doInBackground() 方法就在 call() 中方法,所以我們自定義的耗時任務邏輯得到執行,不就是我們第二部分講的那一套嗎!
doInBackground() 的返回值會傳遞給 postResult() 方法:
就是通過 Handler 將最終的耗時任務結果從子線程發送到主線程,具體的過程是這樣的, getHandler() 得到的就是 AsyncTask 構造函數中初始化的 mHandler , mHander 又是通過 getMainHandler() 賦值的:
可以在看到 sHandler 是一個 InternalHandler 類對象:
所以 getHandler() 就是在得到在主線程創建的 InternalHandler 對象,所以
就可以完成耗時任務結果從子線程到主線程的切換,進而可以進行相關UI操作了。
當消息是 MESSAGE_POST_RESULT 時,代表任務執行完成, finish() 方法被調用:
如果任務沒有被取消的話執行 onPostExecute() ,否則執行 onCancelled() 。
如果消息是 MESSAGE_POST_PROGRESS , onProgressUpdate() 方法被執行,根據之前的用法可以 onProgressUpdate() 的執行需要我們手動調用 publishProgress() 方法,就是通過 Handler 來發送進度數據:
進行中的任務如何取消呢?AsyncTask 提供了一個 cancel(boolean mayInterruptIfRunning) ,參數代表是否中斷正在執行的線程任務,但是呢並不靠譜, cancel() 的方法注釋中有這么一段:
大致意思就是調用 cancel() 方法後, onCancelled(Object) 回調方法會在 doInBackground() 之後被執行而 onPostExecute() 將不會被執行,同時你應該 doInBackground() 回調方法中通過 isCancelled() 來檢查任務是否已取消,進而去終止任務的執行!
所以只能自己動手了:
AsyncTask 整體的實現流程就這些了,源碼是最好的老師,自己跟著源碼走一遍有些問題可能就豁然開朗了!
7. 既然android service是運行在主線程中的,那service還有什麼用
你沒有將android 組件和android C/S架構的概念理解清楚,不僅沒有理解清楚,還把組件的概念,跟線程、進程混淆在一起了。 我將android比喻成一棟辦公大樓,android 中進程就是一個辦公室,線程就是辦公室裡面的員工,辦公室是不能幹活的,而真正幹活的是這個辦公室裡面的員工。一個員工只能在一個辦公室裡面幹活,而一個辦公室可以有很多員工。 Android的老闆希望它的公司能辦理的井井有條,於是針對每一種職能專門設立管理部門,例如WMS,負責窗口管理的,例如MPS,負責多媒體播放的。 一個部門可以有一個或多個辦公室,一個辦公室也可以有多個部門。 而android的管理部門往往是不幹什麼實事的,就像我們的天朝的猿類,你推它一下,它才動一下。所以android需要一些干實事的部門,做對外客戶的,這些部門我們統稱為apk。Android中有好多這種部門,於是為了防止這些部門瞎干,又把部門分成Activity、Service、BrocastReceiver、ContentProvider四種子部門,這些子部門就是用來跟其它部門做溝通的,而所有的子部門運作時都會由大管家AMS來記錄在案。 Activity,做門面的。 Service,做對外支持的。 BrocastReceiver,做門衛收信的。 ContentProvider,做倉庫管理的。 做門面的,可以做對外支持的活,也可以做倉庫管理的活。但是外面可不這么認為,它想找你要數據,只會找ContentProvier,找對外支持只會找Service。 另外AMS大管家有個不好的習慣,它為了節省公司的資源,AMS那裡沒有你這個apk任何部門運行記錄的時候,它有可能把你的電關了(殺進程)。 而LZ你描述的問題呢,就是你的部門想下載東西,是由Activity子部門去干呢,還是Service去干。
8. Android中服務service
本文原文連接 https://blog.csdn.net/wen20102321/article/details/53155736
Service是Android中的四大組件之一,它的級別和Activity差不多。只不過Service沒有頁面顯示,只能後台運行,可以和其他組件進行交互。
Service的後台運行並不是子線程,是在主線程中進行的,只是它沒有界面顯示。如果Service進行了耗時操作同樣需要開啟子線程,否則會跟Activity一樣出現ANR問題(application not response–程序沒有響應)。
補充說明:
主線程的內容包括UI和後台,只要程序中的UI或者後台其中一個在跑,程序都算是在運行狀態。
1,創建一個自己的TestService繼承Service
2,必須實現重寫其中的onBind方法,可以在里邊做各種操作,也可以接收傳遞過來的Intent的數據。
(在Android Studio中可以直接新建一個Service)
服務的注冊是四大組件中最簡單的一個,一般只要設置name屬性就可以了。
1,startService()啟動
(1)啟動服務startService:onCerate(),onStart()
(2)停止服務stopService:onDestroy()
此方法啟動服務,服務如果未被創建,系統會先調用onCreate()方法,接著調用onStrat()方法。如果調用startService前服務已經被啟動,多次調用啟動方法,不會多次調用onCreate,但會導致多次調用onStrat。
2,bindService()啟動
(1)綁定bindService:onCreate(),onBind()
(2)解除綁定unbindService:onUnbind()
(3)正常停止程序服務的方法是先接觸綁定unbindService,在停止服務stopService
綁定後調用stopService方法,這時候是不能停止服務的,如果這時再調用解綁unbindService,程序會先解綁,後停止服務。
用此方法啟動服務,在服務未被創建時,會先調用onCreate(),接著調用onBind()方法,這時候調用者和服務綁定在一起,調用者退出,系統會先調用服務的onUnbind(),然後onDestroy()。如果調用bindService之前服務已經被綁定,多次調用bindService並不會導致onCreate()和onBind()方法被多次調用。如果調用者想與正在綁定的服務解除綁定,可以調用unbindService()。
(1),onCerate()服務第一次被創建
(2),onStartComand()服務開始工作
(3),onBind()服務已經綁定
(4),onUnBind()服務解綁
(5),onDestroy()服務已經停止
普通的Service進行耗時操作要創建一個線程去完成,因為service是在主線程運行的,並且這個子線程完成工作要手動停止 。IntentService是繼承了Service並處理起步請求的一個類,在IntentService內有一個工作線程,來處理耗時操作,啟動IntentService的方式和啟動傳統的Service是一樣,當任務執行完成後,IntentService會自動停止,而不需要我們去控制。
可以啟動多次IntentService,每一個耗時操作會以工作隊列的方式在IntentService的onHandleIntent回調方法中執行,並且每次只會執行一個工作線程,執行完第一個再執行第二個,以此類推,而且,所有請求都在一個單線程中,不會阻塞主線程,同一時間只處理一個請求。
IntentService優點
1,省去了在Service中開線程的麻煩
2,當操作完成時,不用手動停止Service。IntentService是Service,但是比Service更智能。
9. android service是運行在主線程嗎
是的,所以如果你要做網路請求的話,即使在服務里也用在子線程里操作
否則會卡主界面
10. Android中進程與線程及如何在子線程中操作U
一個Android 程序默認情況只有一個進程,但是一個進程可以有多個線程。其中有一個UI 線程也稱為UI主線程,UI Thread在Android程序運行的時候就被創建,主要是負責控制UI界面的顯示、更新和控制項交互。所有的Android應用程序組件----包括Activity、Service、Broadcast Receiver都在應用程序的主線程中運行。因此,任何組件中的費時操作處理都可能阻塞所有其他的組件、包括Service和可見的Activity。
在Android 中,對未響應的定義是:Activity對一個輸入事件在5s內沒有響應,或者Broadcast Receiver在10s內沒有完成他的onReceive處理程序。對於任何不用直接和用戶界面進行交互的重要處理,使用後台線程技術處理是非常重要的,將文件操作、網路交互、資料庫、復雜計算調度到後台線程中完成非常重要,以免阻塞主線程。
方法一:Thread+Handler
開啟一個新線程:new Thread(new MyThread()).start();
//通過Handler物件,通知主線程UI Thread來更新界面
Handler myHandler=new Handler(){
//此方法主要用於更新UI
public void handleMessage(Message msg){
switch(msg.what){
//根據Thread返回的標識進行相應的處理
}
}
};
class MyThread implements Runnable{
public void run(){
int what=0;
//將耗時操作放到這里處理
//to-do