android服務啟動
1. Android重學系列 Service 啟動和綁定原理
我們已經了解了BroadcastReceiver的原理,我們再來看看四大組件之一的Service是怎麼啟動的,以及怎麼運行的原理。
如果遇到什麼問題可以來到 https://www.jianshu.com/p/c4927c0b80a9 本文下進行交流
啟動Service的入口就是startService和bindService方法。我們先來看看startService在ContextImpl中做了什麼。
文件:/ frameworks / base / core / java / android / app / ContextImpl.java
此時調用的就是AMS的startService方法。
mServices是一個ActiveServices對象。這個對象是在AMS的構造函數中初始化好的。
這里調用了ActiveServices的startServiceLocked。
文件:/ frameworks / base / services / core / java / com / android / server / am / ActiveServices.java
核心流程有如下三個:
注意這里addToStarting是一個比較關鍵的判斷,addToStarting默認為false。
如果此時不是啟動前台服務,則需要進一步進行處理。如果ProcessRecord為空或者curProcState大於PROCESS_STATE_RECEIVER這個優先順序數值;也就是優先順序更小。
為了避免此時App應用是沒有任何的前台ui,或者App應用還沒有聲明。避免有的App通過startService進行應用的包活或者拉起應用。就會進行如下能夠存在的最大後台服務數量,則放入mDelayedStartList中進行延時啟動後台服務,現在直接返回了。
不然則說明能夠允許啟動後台服務, 就設置為addToStarting為true。
通過ComponentName也就是包名和類名查找ServiceRecord;通過Intent意圖過濾找到ServiceRecord。·
核心方法是bringUpServiceLocked。如果bringUpServiceLocked返回了異常,就返回一個特殊的ComponentName對象。
addToStarting為true,說明此時是一個能夠啟動的後台服務,則ServiceRecord添加到mStartingBackground中。如果mStartingBackground的數量為0,則直接調用ServiceMap的rescheleDelayedStartsLocked啟動後台服務。
這幾個關鍵的步驟,讓我們依次的考察,先來看看scheleCreateService中做了什麼。
如果第一次啟動就走第一個if的分支:
能看到和BroadcastReceiver的ANR思路一樣,通過一個延時的Handler,如果達到時間了還沒有移除這個Handler消息則報ANR異常。
這里根據啟動前台和後台分為兩種超時時間:
前台分別是10秒,後台服務不屬於後台進程組(判斷adj是否在SCHED_GROUP_BACKGROUND)是20秒,後台服務屬於後台進程組 200秒。
把數據封裝成CreateServiceData後,通過Handler調用如下方法:
透三點的核心原理可以看我寫的的Application創建和BroadcastReceiver原理兩篇文章。來看看Service中都做了什麼?
很簡單就是保存了傳遞過來的參數,值得注意的是這個IBinder對象其實就是指ServiceRecord對象。
接著執行Service.onCreate這個空實現的方法。
本質上還是調用了ActiveServices的serviceDoneExecutingLocked方法。
type是SERVICE_DONE_EXECUTING_ANON,所不會做更多的處理。 最後執行了serviceDoneExecutingLocked方法。
這個方法不斷的循環遍歷List<ServiceStartArgs>分發SERVICE_ARGS消息,這個消息通過主線程的Looper調用handleServiceArgs。
bindService在開發中用的不是很多,這里稍微提一下他的使用。
首先申明一個ServiceConnection對象,用於綁定服務端的Service。
調用bindService的方法綁定到某個Service中。當服務端的service成功回調onBind方法,我們只需要返回對應的Binder對象。就能使用調用bindService的客戶端在ServiceConnection的onServiceConnected的回調中獲得Binder對象。
之後就能通過這個Binder調用本進程或者其他進程的的方法了。實際上我們可以把這個過程看成一個多對多的服務-客戶端模型。多個客戶端通過Binder向多服務端Service通信,每一次我們都可以通過ComponentName判斷不同服務返回來的Binder對象。
這裡面很簡單,和BroadcastReceiver的思路很像。動態注冊的BroadcastReceiver會封裝成一個ReceiverDispatcher,而這里把ServiceConnection封裝成LoadedApk.ServiceDispatcher對象。
並且會把ServiceDispatcher作為value,ServiceConnection作為key緩存一個map中。並且以context為key,把這個臨時的map作為value緩存起來。這樣一個Context就映射有了多個ServiceDispatcher對象,也就可以注冊多個監聽被綁定Service狀態的監聽者了。
2. Android輸入法IMMS服務啟動流程(3)(啟動IMS應用)
接上一篇,IMMS設置當前默認輸入法為LatinIME輸入法後,調用onCreate方法,然後會調用startInputInnerLocked啟動輸入法LatinIME的服務
本章節主要分析,onCreate生命周期中,各個流程調用
bindServiceAsUser啟動的服務是LatinIME
如上圖流程圖,服務啟動後,會調用到InputMethodManagerService的方法
該流程的主要邏輯:
完成對mMethodList和mMethodMap的數據初始化;檢查當前默認的輸入法(LatinIME)服務是否存在,很明顯,經過systemrunning過程以後,
mMethodMap已經包含了LatinIME,因此不會重復執行選擇和設定另外輸入法為默認輸入法的操作
該方法主要是檢查默認的LatinIME是否是可用的可用的輸入法,如果不可用,則設置為可用;
對應的settingprovider欄位為:
經過以上流程後,默認輸入法依然為LatinIME輸入法,該流程的主要作用為,將啟動的輸入法應用更新到可用列表enabled_input_methods中;
不過,目前默認的輸入法依然為LatinIME輸入法,跟重啟手機前,我們設置的輸入法(搜狗輸入法)依然不一致
下一篇文章,我們研究下,輸入法啟動過程中的onBind和onServiceConnected流程
3. Android 啟動後台運行程序(Service)
Android開發中,當需要創建在後台運行的程序的時候,就要使用到Service。Service 可以分為有無限生命和有限生命兩種。
特別需要注意的是Service跟Activities是不同的(簡單來說可以理解為後台與前台的區別),例如,如果需要使用Service的話,需要調用startService(),從而利用startService()去調用Service中的OnCreate()和onStart()方法來啟動一個後台的Service。
啟動一個Service的過程如下:context.startService() ->onCreate()- >onStart()->Service running其中onCreate()可以進行一些服務的初始化工作,onStart()則啟動服務。
停止一個Service的過程如下:context.stopService() | ->onDestroy() ->Service stop
接下來的實例是一個利用後台服務播放音樂的小例子,點擊start運行服務,點擊stop停止服務。ServicesDemo.java(是一個Activity)
除此之外還要在Manifest裡面聲明服務:(AndroidManifest.xml)
定義Service(MyService.java)
layout文件夾中是main.xml
values 文件夾中是strings.xm
4. Android 開機自啟動service實踐
Android 設備啟動的時候,會發送android.intent.action.BOOT_COMPLETED的廣播,監聽這個廣播來實現開機自啟動。
1) 創建需要的service和 BroadcastReceiver
2) 在AndroidManifest.xml 注冊service 和BroadcastReceiver
3)申明許可權
```
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
}
5. Android應用程序啟動流程總結
AMS主要功能:
AMS是Android中最核心的服務,主要負責系統中四大組件的啟動、切換、調度及應用進程的管理和調度等工作。還負責啟動或殺死應用程序的進程。
WMS主要功能:
為所有窗口分配Surface。
管理Surface的顯示順序、尺寸、位置。
管理窗口動畫。
輸入系統相關:WMS是派發系統按鍵和觸摸消息的最佳人選,當接收到一個觸摸事件,它需要尋找一個最合適的窗口來處理消息。
PWS主要功能:
PMS 用來管理跟蹤所有應用APK,包括安裝,卸載,解析,控制許可權等。
SystemServer也是一個進程,包括AMS、PMS、WMS等等。
zygote意為「受精卵「。Android是基於linux系統的,而在Linux中,所有的進程都是由init進程直接或者是間接fork出來的,zygote進程也不例外。
App進程是用戶點擊桌面icon時,通過Launcher進程請求SystemServer,再調用Zygote孵化的。
①點擊啟動一個App,Launcher進程採用Binder IPC向ActivityManagerService發起startActivity請求;
②ActivityManagerService接收到請求後,向zygote進程發送創建進程的請求;
③Zygote進程fork出新的子進程,即App進程;
④App進程通過Binder IPC向sytem_server進程發起綁定Application請求;
⑤system_server進程在收到請求後,進行一系列准備工作後,再通過binder IPC向App進程發送scheleLaunchActivity請求;
⑥App進程的binder線程(ApplicationThread)在收到請求後,通過handler向主線程發送LAUNCH_ACTIVITY消息;
⑦主線程在收到Message後,通過發射機制創建目標Activity,並回調Activity.onCreate()等方法。
⑧到此,App便正式啟動,開始進入Activity生命周期,執行完onCreate/onStart/onResume方法,UI渲染結束後便可以看到App的主界面。
備註:
Launcher,PMS,Zygote,App進程是三個獨立的進程,相互通信就需要使用進程間通信機制。與Zygote通信是使用的socket通信,Launcher,PMS,App進程間使用的是Binder機制。
6. Android 之 Service(一)啟動,綁定服務
Service(服務)一個運行在後台執行長時間運行的操作組件,它不提供任何用戶界面,作為與Activity同級的組件,它依舊是運行在主線程中。
其它組件可以啟動一個Service,當這個Service啟動之後便會在後台執行,這里需要注意,由於是在主線程中,所以我們需要另外開啟一個線程來執行我們的耗時操作。
此外,一個組件還可以與一個Service進行綁定來實現組件之間的交互,甚至可以執行IPC(Inter-Process Communication)進程間通信。
Service可以在後台執行很多任務,比如處理網路事務,播放音樂,文件讀寫或者與一個內容提供者交互,等等。
本地服務(Local)
該服務依附在主進程上而不是獨立的進程,這樣在一定程度上節約了資源,另外本地服務因為是在同一進程因此不需要IPC,也不需要AIDL。相應bindService會方便很多,當主進程被Kill後,服務便會終止。一般使用在音樂播放器播放等不需要常駐的服務。
遠程服務(Remote Service)
該服務是獨立的進程,對應進程名格式為所在包名加上你指定的android:process字元串。一般定義方式 android:process=":service" 由於是獨立的進程,因此在Activity所在進程被Kill的時候,該服務依然在運行,不受其他進程影響,有利於為多個進程提供服務具有較高的靈活性。由於是獨立的進程,會佔用一定資源,並且使用AIDL進行IPC比較麻煩。一般用於系統的Service,這種Service是常駐的。
startService啟動的服務
用於啟動一個服務執行後台任務,不與組件進行通信,停止服務使用stopService。 當一個應用組件比如activity通過調用startService()來啟動一個服務的時候,服務便處於啟動狀態。一旦啟動,服務可以在後台無限期地運行下去,即使當啟動它的組件已經銷毀。通常情況下,一個啟動的service執行一個單一的操作並且不會返回任何結果給調用者。
bindService啟動的服務
用於啟動的服務需要進行通信。停止服務使用unbindService。 當一個應用組件通過調用bindService()來與一個服務綁定時,服務便處於綁定狀態。一個綁定的服務提供了一個客戶端-伺服器端介面來允許組件與服務進行交互,發送請求,得到結果甚至通過IPC進程間通信來完成操作。只有當其它組件與服務進行綁定時,服務才會處於綁定狀態。多個組件可以同時與服務綁定,但是當他們全部都解除綁定時,服務就會銷毀。
2.BindService:
如果一個Service在某個Activity中被調用bindService方法啟動,不論bindService被調用幾次,Service的 onCreate 方法只會執行一次,同時 onStartCommand 方法始終不會調用。當建立連接後,Service會一直運行,除非調用unbindService來接觸綁定、斷開連接或調用該Service的Context不存在了(如Activity被Finish——即通過bindService啟動的Service的生命周期依附於啟動它的Context),系統在這時會自動停止該Service。
3.StartService AND BindService:
當一個Service在被啟動(startService 的同時又被綁定(bindService ),該Service將會一直在後台運行,並且不管調用幾次, onCreate 方法始終只會調用一次, onStartCommand 的調用次數與startService 調用的次數一致(使用bindService 方法不會調用 onStartCommand )。同時,調用unBindService 將不會停止Service,必須調用stopService 或Service自身的stopSelf 來停止服務。
4.停止Service:
當一個服務被終止(stopService 、stopSelf 、unbindService )時, onDestory 方法將會被調用——所以我們需要在該方法中清除一些工作(依附該Service生命周期上的,比如:停止在Service中創建並運行的線程)。
1.創建服務
如果你才用的是 startService的方式那麼 onBind方法可以忽略
2.注冊服務
3.開啟服務
start:
bind
綁定服務,一般涉及到組件或進程之間的通信,既然需要通信,那麼我們肯定需要一個連接,這里ServiceConnection就是我們所需要的連接,通過Ibinder的傳遞,我們可以獲取到Service的Ibinder對象,從而進行相關操作。
關於粘性服務,這里需要提到 Service的onStartCommand返回值
andorid:name
adroid:exported
android:enabled
android:label
android:process
android:icon
android:permission
關於服務,當我們在應用開發中,如果需要長時間的在後台運行,獨立完成某一些事情的情況下,請使用Service!
此文綜合: http://www.jianshu.com/p/1e49e93c3ec8 以及自己的一些問題看法,用作學習,回顧之用。
Service 前台服務
請參看 紫豪 http://www.jianshu.com/p/5505390503fa
7. Android啟動過程深入解析
當按下Android設備電源鍵時究竟發生了什麼?
Android的啟動過程是怎麼樣的?
什麼是Linux內核?
桌面系統linux內核與Android系統linux內核有什麼區別?
什麼是引導裝載程序?
什麼是Zygote?
什麼是X86以及ARM linux?
什麼是init.rc?
什麼是系統服務?
當我們想到Android啟動過程時,腦海中總是冒出很多疑問。本文將介紹Android的啟動過程,希望能幫助你找到上面這些問題的答案。
Android是一個基於Linux的開源操作系統。x86(x86是一系列的基於intel 8086 CPU的計算機微處理器指令集架構)是linux內核部署最常見的系統。然而,所有的Android設備都是運行在ARM處理器(ARM 源自進階精簡指令集機器,源自ARM架構)上,除了英特爾的Xolo設備(http://xolo.in/xolo-x900-features)。Xolo來源自凌動1.6GHz x86處理器。Android設備或者嵌入設備或者基於linux的ARM設備的啟動過程與桌面版本相比稍微有些差別。這篇文章中,我將解釋Android設備的啟動過程。深入linux啟動過程是一篇講桌面linux啟動過程的好文。
當你按下電源開關後Android設備執行了以下步驟。
此處圖片中step2中的一個單詞拼寫錯了,Boot Loaeder應該為Boot Loader(多謝@jameslast 提醒)
第一步:啟動電源以及系統啟動
當電源按下,引導晶元代碼開始從預定義的地方(固化在ROM)開始執行。載入引導程序到RAM,然後執行。
第二步:引導程序
引導程序是在Android操作系統開始運行前的一個小程序。引導程序是運行的第一個程序,因此它是針對特定的主板與晶元的。設備製造商要麼使用很受歡迎的引導程序比如redboot、uboot、qi bootloader或者開發自己的引導程序,它不是Android操作系統的一部分。引導程序是OEM廠商或者運營商加鎖和限制的地方。
引導程序分兩個階段執行。第一個階段,檢測外部的RAM以及載入對第二階段有用的程序;第二階段,引導程序設置網路、內存等等。這些對於運行內核是必要的,為了達到特殊的目標,引導程序可以根據配置參數或者輸入數據設置內核。
Android引導程序可以在找到。
傳統的載入器包含的個文件,需要在這里說明:
init.s初始化堆棧,清零BBS段,調用main.c的_main()函數;
main.c初始化硬體(鬧鍾、主板、鍵盤、控制台),創建linux標簽。
更多關於Android引導程序的可以在這里了解。
第三步:內核
Android內核與桌面linux內核啟動的方式差不多。內核啟動時,設置緩存、被保護存儲器、計劃列表,載入驅動。當內核完成系統設置,它首先在系統文件中尋找」init」文件,然後啟動root進程或者系統的第一個進程。
第四步:init進程
init是第一個進程,我們可以說它是root進程或者說有進程的父進程。init進程有兩個責任,一是掛載目錄,比如/sys、/dev、/proc,二是運行init.rc腳本。
init進程可以在/system/core/init找到。
init.rc文件可以在/system/core/rootdir/init.rc找到。
readme.txt可以在/system/core/init/readme.txt找到。
對於init.rc文件,Android中有特定的格式以及規則。在Android中,我們叫做Android初始化語言。
Action(動作):動作是以命令流程命名的,有一個觸發器決定動作是否發生。
語法
1
2
3
4
5
; html-script: false ]
on <trigger>
<command>
<command>
<command>
Service(服務):服務是init進程啟動的程序、當服務退出時init進程會視情況重啟服務。
語法
1
2
3
4
5
; html-script: false ]
service <name> <pathname> [<argument>]*
<option>
<option>
...
Options(選項)
選項是對服務的描述。它們影響init進程如何以及何時啟動服務。
咱們來看看默認的init.rc文件。這里我只列出了主要的事件以及服務。
Table
Action/Service
描述
on early-init
設置init進程以及它創建的子進程的優先順序,設置init進程的安全環境
on init
設置全局環境,為cpu accounting創建cgroup(資源控制)掛載點
on fs
掛載mtd分區
on post-fs
改變系統目錄的訪問許可權
on post-fs-data
改變/data目錄以及它的子目錄的訪問許可權
on boot
基本網路的初始化,內存管理等等
service servicemanager
啟動系統管理器管理所有的本地服務,比如位置、音頻、Shared preference等等…
service zygote
啟動zygote作為應用進程
在這個階段你可以在設備的屏幕上看到「Android」logo了。
第五步
在Java中,我們知道不同的虛擬機實例會為不同的應用分配不同的內存。假如Android應用應該盡可能快地啟動,但如果Android系統為每一個應用啟動不同的Dalvik虛擬機實例,就會消耗大量的內存以及時間。因此,為了克服這個問題,Android系統創造了」Zygote」。Zygote讓Dalvik虛擬機共享代碼、低內存佔用以及最小的啟動時間成為可能。Zygote是一個虛擬器進程,正如我們在前一個步驟所說的在系統引導的時候啟動。Zygote預載入以及初始化核心庫類。通常,這些核心類一般是只讀的,也是Android SDK或者核心框架的一部分。在Java虛擬機中,每一個實例都有它自己的核心庫類文件和堆對象的拷貝。
Zygote載入進程
載入ZygoteInit類,源代碼:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
registerZygoteSocket()為zygote命令連接注冊一個伺服器套接字。
preloadClassed 「preloaded-classes」是一個簡單的包含一系列需要預載入類的文本文件,你可以在/frameworks/base找到「preloaded-classes」文件。
preloadResources() preloadResources也意味著本地主題、布局以及android.R文件中包含的所有東西都會用這個方法載入。
在這個階段,你可以看到啟動動畫。
第六步:系統服務或服務
完成了上面幾步之後,運行環境請求Zygote運行系統服務。系統服務同時使用native以及java編寫,系統服務可以認為是一個進程。同一個系統服務在Android SDK可以以System Services形式獲得。系統服務包含了所有的System Services。
Zygote創建新的進程去啟動系統服務。你可以在ZygoteInit類的」startSystemServer」方法中找到源代碼。
核心服務:
啟動電源管理器;
創建Activity管理器;
啟動電話注冊;
啟動包管理器;
設置Activity管理服務為系統進程;
啟動上下文管理器;
啟動系統Context Providers;
啟動電池服務;
啟動定時管理器;
啟動感測服務;
啟動窗口管理器;
啟動藍牙服務;
啟動掛載服務。
其他服務:
啟動狀態欄服務;
啟動硬體服務;
啟動網路狀態服務;
啟動網路連接服務;
啟動通知管理器;
啟動設備存儲監視服務;
啟動定位管理器;
啟動搜索服務;
啟動剪切板服務;
啟動登記服務;
啟動壁紙服務;
啟動音頻服務;
啟動耳機監聽;
啟動AdbSettingsObserver(處理adb命令)。
第七步:引導完成
一旦系統服務在內存中跑起來了,Android就完成了引導過程。在這個時候「ACTION_BOOT_COMPLETED」開機啟動廣播就會發出去。
8. Android Service啟動Activity
Android Service 基礎知識點
我們都知道Activity中啟動Activity,只需要startActivity,如果在Service中啟動Activity呢?
在Service中啟動Activity,很多人說在非Activity中啟動Activity需要加FLAG_ACTIVITY_NEW_TASK flag,如果我不加會怎麼樣呢?
並沒有出現異常和崩潰,跳轉也是正常的,但是與之前所說的會崩潰報出異常不符合啊?!難道是與版本有關嗎?於是我使用了Android 23去測試果然拋出了異常
ContextImpl在Android studio中屬於隱藏源碼,在IDE中可能看不到,那就需要在SDK中去找 我的是:D:\AndroidSdk\sources\android-23\android\app\ContextImpl.java
可以看到只是判斷條件不同而已,android-23中發現沒有Intent.FLAG_ACTIVITY_NEW_TASK會直接拋出異常,而android-26中我們在非 Activity 調用 startActivity() 的時候,我們這個 options 通常是 null 的,所以在 26 之間的時候,誤把判斷條件 options == null 寫成了 options != null 導致進不去 if,從而不會拋出異常
附加:在android 24-android 27(即android N-android O)之間出現了bug,也就是說即使沒有加Intent.FLAG_ACTIVITY_NEW_TASK也會正常跳轉
可以很明顯看到判斷條件targetSdkVersion < Build.VERSION_CODES.N || targetSdkVersion >= Build.VERSION_CODES.P 即在24-27
看Activity中啟動Activity的源碼
Activity.startActivity() ->startActivityForResult()->mInstrumentation.execStartActivity() ...最終還是Ams去啟動Activity 也就是Activity中重寫了startActivity()方法所以不會出現這個異常
其實直觀很好理解,如果不是在Activity中啟動的,那就可以看做不是用戶主動的行為,也就說這個界面可能出現在任何APP之上,如果不用Intent.FLAG_ACTIVITY_NEW_TASK將其限制在自己的Task中,那用戶可能會認為該Activity是當前可見APP的頁面,這是不合理的。舉個例子:我們在聽音樂,這個時候如果郵件Service突然要打開一個Activity,如果不用Intent.FLAG_ACTIVITY_NEW_TASK做限制,那用戶可能認為這個Activity是屬於音樂APP的,因為用戶點擊返回的時候,可能會回到音樂,而不是郵件(如果郵件之前就有界面)
對比源碼發現,在我們非 Activity 調用 startActivity() 的時候,我們這個 options 通常是 null 的,所以在 24~27 之間的時候,誤把判斷條件 options == null 寫成了 options != null 導致進不去 if,從而不會拋出異常,如此我們使用 Context.startActivity() 的時候是一定要加上 FLAG_ACTIVITY_NEW_TASK 的,但是在 Android N 到 O-MR1,即 24~27 之間卻出現了 bug,即使沒有加也會正確跳轉
結語:感謝各位大佬的分享,對此有疑問的可以去運行跑一下,看一下相關的源碼,如有錯誤的需要改進的地方,請留言評論指出,謝謝!
參考文章:
9. 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更智能。