IntentService小酌
前言:生活受到嚴重的打擊,又要投身到學習中,在程式碼中墮落。
IntentService是一個我們不常使用的類,可以說涉及到Service的我們都很少使用。最近有幸接觸這一個類,使用過程中發現這個類出乎意料的簡單,簡直是不學白不學,學習的過程中還能夠對Handler的知識進一步深入瞭解一下。
介紹
這是一個按要求處理非同步的請求(通過intent)繼承自Service的抽象子類。客戶端通過startService傳送請求傳遞Intent,開啟一個服務並且用一個工作執行緒輪流解決每一個intent,當結束工作後自動關閉服務。(依然擁有Service的特性,所以當我們在Service還沒關閉的時候呼叫Service,那麼不會建立新的Service,也就不會執行onCreate,但要是startService的時候,前一個請求已經執行完畢,那麼將會重新建立Service,執行onCreate)
實現這個IntentService類需要實現一個繼承自IntentService的子類,並且實現裡面的onHandleIntent(Intent)抽象方法,IntentService通過startService接收Intent後,在建立的時候建立一個工作執行緒,通過Handler傳送訊息傳遞Intent,,並且在執行完畢該Intent後試圖關閉。
所有的請求都會在一個單一的工作執行緒處理,它們不會阻塞主執行緒的loop,但一次只會處理一個請求。如果你想下載10個檔案,呼叫10次startService,那麼就會依次下載10個檔案。
構造方法
構造方法需要傳遞一個name引數,主要用於命名工作執行緒,對除錯比較重要。
對於onBind,IntentService的預設實現是返回null,也可以理解為預設不與任何元件繫結,除非我們需要將它和某個元件繫結,不然不需要重寫這個方法,但是出於對IntentService的設計考慮,我認為我們不應該重寫這個方法,不然使用IntentService就沒有意義了。
Handler訊息機制
我們呼叫onStart還是onStartComand,都會執行onStart的操作
既然使用到了Handler,那麼我們就要看一下IntentService是怎麼實現這個訊息傳遞的,以及怎麼處理訊息的:
構造方法傳入了一個Looper,而handlerMessage中則是獲取訊息中的Intent,然後呼叫onHandleIntent方法,執行完之後就會根據startId來關閉service,需要注意的是stopSelf(int startId )這個方法,這個方法會嘗試關閉Service,只是嘗試而已,每次通過startService( )啟動的服務,系統都會生成一個startId,並且在onStartCommand中可以獲得這個startId。但是,只有當stopSelf裡面的startId等於最後一次呼叫startService( )所生成的startId,才會真正停止服務,否則服務是不會停止的。so easy。那麼IntentService是怎麼開啟一個工作執行緒來執行任務呢?前面已經提及到,我們來看一下IntentService中的onCreate方法:
很明顯HandlerThread建立了一個執行緒,而這個執行緒是單一的,通過這個執行緒獲取Looper,並且使用這個Looper來輪訓訊息佇列MessageQueue。要知道,每個執行緒中有一個Looper,每一個Looper中有一個訊息佇列,而Looper會一直從訊息佇列中輪訓訊息,然後執行handler的handleMessage方法,就有了上面的步驟了,那麼可想而知,handleIntent是在哪個執行緒執行呢,自然是Looper所在的執行緒,也就是HandlerThread建立的這個執行緒了。
Handler(Looper looper)會直接呼叫this(looper,null,false),也就是上面的構造方法。而HandlerThread是一個繼承Thread類的子類,並且這個執行緒會有一個Looper。呼叫start()方法就會呼叫Looper的prepare和loop方法。到此,你就可以自己寫一個IntentService了,而這個IntentService可以做一些Intent級的後臺工作。
應用
比如,很多時候我們會在Application中做一些第三方類庫的初始化,但是當我們的類庫越來越多,或者第三方類庫的初始化越來越複雜的時候就會出現一個問題,開機時間過長,俗稱(冷啟動時間過長)。要知道,我們初始化我們的應用,做的可不僅僅是這些初始化第三方,如果都放在主執行緒中進行的話,那麼勢必會出現問題。而為了優化這個問題,我們可以嘗試使用IntentService來進行一些第三方類庫的初始化操作。好比如:
在檢視程式碼的過程中,我發現了一個比較有趣的東西,就是activity中的runOnUiThread這個方法
程式碼很簡單,如果不在主執行緒,那麼就使用mHandler傳送訊息,如果在主執行緒,那麼就直接執行。簡而言之,實現非同步的所有方法(非同步的概念是不用阻塞當前的執行緒來等待處理結果,允許後續操作,並且等其他執行緒處理完成,通過回撥通知此執行緒),僅且只有一種,那就是handler,而其餘的所有方法,都是對handler的一種封裝而已,有人可能會對IntentService的非同步不是很瞭解,要知道,IntentService繼承自Service,Service是一個在主執行緒執行的元件,只是這個元件執行在後臺而已,看不到的東西俗稱叫後臺。所以在這個Service內,我們可以通過handleIntent來實現一些非同步操作,當然了,在handleIntent中需要想辦法把訊息傳送到主執行緒的handler,才會達到非同步的需求。
總結
唉,當我們真正想了解一個類的時候,常常會發現研究程式碼的時候會涉及到越來越多的API,越來越多的機制和程式碼,即使簡單如AsyncTask,雖然程式碼量不多,但是展開了研究也是夠嗆,所以我們在研究程式碼的時候,點到即止,不然只會越來越混亂,比如說,我們通過檢視IntentService的程式碼從而得知這個API的特性:在Service中開啟一個工作執行緒執行Intent,並且在任務執行完畢後嘗試停止Service。
相關文章
- IntentServiceIntent
- 理解 IntentService 原理Intent
- IntentService的使用Intent
- Android IntentServiceAndroidIntent
- IntentService原始碼Intent原始碼
- IntentService簡介Intent
- Android 使用IntentServiceAndroidIntent
- IntentService,用完即走Intent
- 淺談IntentService原理分析Intent
- Android IntentService 工作原理AndroidIntent
- 從原始碼分析IntentService原始碼Intent
- Android面試相關 - IntentServiceAndroid面試Intent
- IntentService 和 HandlerThread 的原理Intentthread
- HandlerThread和IntentService原始碼解析threadIntent原始碼
- Android中IntentService原始碼分析AndroidIntent原始碼
- Android IntentService 的使用和解析AndroidIntent
- 活兒好又不糾纏的 IntentServiceIntent
- Android多執行緒之IntentServiceAndroid執行緒Intent
- 用IntentService 與ResultReceiver連線web serviceIntentWeb
- Android中IntentService的原理及使用AndroidIntent
- Android IntentService完全解析 當Service遇到HandlerAndroidIntent
- Android後臺任務(HandlerThread、AsyncTask、IntentService)AndroidthreadIntent
- Android中IntentService的使用及其原始碼解析AndroidIntent原始碼
- Android四大元件之Service,以及IntentServiceAndroid元件Intent
- Android IntentService使用全面介紹及原始碼解析AndroidIntent原始碼
- Android Service和IntentService知識點詳細總結AndroidIntent
- 2018.03.16、Android-IntentService學習筆記AndroidIntent筆記
- 看完這一篇,再也不怕面試官問到IntentService的原理面試Intent
- App 冷啟動緩慢出現白屏之終極解決方案 — IntentService 高效非同步處理APPIntent非同步