IntentService 深入分析

官方的解釋是:

IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through android.content.Context.startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.

This "work queue processor" pattern is commonly used to offload tasks from an application's main thread. The IntentService class exists to simplify this pattern and take care of the mechanics. To use it, extend IntentService and implementonHandleIntent(Intent). IntentService will receive the Intents, launch a worker thread, and stop the service as appropriate.

All requests are handled on a single worker thread -- they may take as long as necessary (and will not block the application's main loop), but only one request will be processed at a time.

意思是說:IntentService是一個通過Context.startService(Intent)啟動可以處理異步請求的Service,使用時你只需要繼承IntentService和重寫其中的onHandleIntent(Intent)方法接收一個Intent對象,在適當?shù)臅r候會停止自己(一般在工作完成的時候). 所有的請求的處理都在一個工作線程中完成,它們會交替執(zhí)行(但不會阻塞主線程的執(zhí)行),一次只能執(zhí)行一個請求.(**本人修改了原文的一些翻譯)

下面是要分析的源碼:

public abstract class IntentService extends Service {

? ? ? ? private volatile Looper mServiceLooper;

? ? ? ? private volatile ServiceHandler mServiceHandler;

? ? ? ? private String mName;

? ? ? ? private boolean mRedelivery;


? ? ? ? private finalclass ServiceHandler extends Handler {

? ? ? ? ? ? ? ? public ServiceHandler(Looper looper) {

? ? ? ? ? ? ? ? ? ? ? ? super(looper);

? ? ? ? ? ? ? ? }


? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? public void handleMessage(Message msg) {

? ? ? ? ? ? ? ? ? ? ? ? onHandleIntent((Intent)msg.obj);

? ? ? ? ? ? ? ? ? ? ? ? stopSelf(msg.arg1);

? ? ? ? ? ? ? ? }

? ? ? ? }

從源碼可以分析出:

IntentService 實際上是Looper,Handler,Service 的集合體,他不僅有服務的功能,還有處理和循環(huán)消息的功能.

下面是onCreate()的源碼:

? ? ? ? @Override

? ? ? ? public void onCreate() {

? ? ? ? ? ? ? ? super.onCreate();

? ? ? ? ? ? ? ? HandlerThread thread = new HandlerThread("IntentService[" + mName +"]");

? ? ? ? ? ? ? ? thread.start();

? ? ? ? ? ? ? ? mServiceLooper = thread.getLooper();

? ? ? ? ? ? ? ? mServiceHandler = new ServiceHandler(mServiceLooper);

? ? ? ? }

分析:IntentService創(chuàng)建時就會創(chuàng)建Handler線程(HandlerThread)并且啟動,然后再得到當前線程的Looper對象來初始化IntentService的mServiceLooper,接著創(chuàng)建mServicehandler對象.

下面是onStart()的源碼:

? ? ? ? @Override

? ? ? ? public void onStart(Intent intent,int startId) {

? ? ? ? ? ? ? ? Message msg = mServiceHandler.obtainMessage();

? ? ? ? ? ? ? ? msg.arg1 = startId;

? ? ? ? ? ? ? ? msg.obj = intent;

? ? ? ? ? ? ? ? mServiceHandler.sendMessage(msg);

? ? ? ? }

分析:當你啟動IntentService的時候,就會產生一條附帶startId和Intent的Message并發(fā)送到MessageQueue中,接下來Looper發(fā)現(xiàn)MessageQueue中有Message的時候,就會停止Handler處理消息,接下來處理的代碼如下:

? ? ? ? @Override

? ? ? ? public void handleMessage(Message msg) {

? ? ? ? ? ? ? ? ? ? ? ? onHandleIntent((Intent)msg.obj);

? ? ? ? ? ? ? ? ? ? ? ? stopSelf(msg.arg1);

? ? ? ? }

接著調用 onHandleIntent((Intent)msg.obj),這是一個抽象的方法,其實就是我們要重寫實現(xiàn)的方法,我們可以在這個方法里面處理我們的工作.當任務完成時就會調用stopSelf(msg.arg1)這個方法來結束指定的工作.

當所有的工作執(zhí)行完后:就會執(zhí)行onDestroy方法,源碼如下:

? ? ? ? @Override

? ? ? ? public void onDestroy() {

? ? ? ? ? ? ? ? mServiceLooper.quit();

? ? ? ? }

服務結束后調用這個方法 mServiceLooper.quit()使looper停下來.

通過對源碼的分析得出:

? ? 這是一個基于消息的服務,每次啟動該服務并不是馬上處理你的工作,而是首先會創(chuàng)建對應的Looper,Handler并且在MessageQueue中添加的附帶客戶Intent的Message對象,當Looper發(fā)現(xiàn)有Message的時候接著得到Intent對象通過在onHandleIntent((Intent)msg.obj)中調用你的處理程序.處理完后即會停止自己的服務.意思是Intent的生命周期跟你的處理的任務是一致的.所以這個類用下載任務中非常好,下載任務結束后服務自身就會結束退出.

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

不知道大家有沒有和我一樣,以前做項目或者練習的時候一直都是用Service來處理后臺耗時操作,卻很少注意到還有個IntentService寞钥,前段時間準備面試的時候看到了一篇關于IntentService的解釋肺魁,發(fā)現(xiàn)了它相對于Service來說有很多更加方便之處,今天在這里稍微來總結下我的心得巩螃。

首先IntentService是繼承自Service的媒峡,那我們先看看Service的官方介紹翠桦,這里列出兩點比較重要的地方:

1.A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.

2.A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).

稍微翻一下(英文水平一般)

1.Service不是一個單獨的進程 苟蹈,它和應用程序在同一個進程中糊渊。

2.Service不是一個線程,所以我們應該避免在Service里面進行耗時的操作

關于第二點我想說下慧脱,不知道很多網上的文章都把耗時的操作直接放在Service的onStart方法中渺绒,而且沒有強調這樣會出現(xiàn)Application Not Responding!希望我的文章能幫大家認清這個誤區(qū)(Service不是一個線程菱鸥,不能直接處理耗時的操作)宗兼。

有人肯定會問,那么為什么我不直接用Thread而要用Service呢氮采?關于這個殷绍,大家可以網上搜搜,這里不過多解釋鹊漠。有一點需要強調主到,如果有耗時操作在Service里,就必須開啟一個單獨的線程來處理G拧5窃俊!這點一定要銘記在心娶靡。

IntentService相對于Service來說牧牢,有幾個非常有用的優(yōu)點,首先我們看看官方文檔的說明:

IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests throughstartService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.

This "work queue processor" pattern is commonly used to offload tasks from an application's main thread. The IntentService class exists to simplify this pattern and take care of the mechanics. To use it, extend IntentService and implement onHandleIntent(Intent). IntentService will receive the Intents, launch a worker thread, and stop the service as appropriate.

All requests are handled on a single worker thread -- they may take as long as necessary (and will not block the application's main loop), but only one request will be processed at a time.

e使用隊列的方式將請求的Intent加入隊列姿锭,然后開啟一個worker thread(線程)來處理隊列中的Intent塔鳍,對于異步的startService請求,IntentService會處理完成一個之后再處理第二個呻此,每一個請求都會在一個單獨的worker thread中處理献幔,不會阻塞應用程序的主線程,這里就給我們提供了一個思路趾诗,如果有耗時的操作與其在Service里面開啟新線程還不如使用IntentService來處理耗時操作蜡感。下面給一個小例子:

1.Service:

? ? package com.zhf.service;


? ? import Android.app.Service;

? ? import Android.content.Intent;

? ? import Android.os.IBinder;


? ? public class MyService extends Service {


? ? @Override

? ? public void onCreate() {

? ? super.onCreate();

? ? }


? ? @Override

? ? public void onStart(Intent intent, int startId) {

? ? super.onStart(intent, startId);

? ? //經測試,Service里面是不能進行耗時的操作的恃泪,必須要手動開啟一個工作線程來處理耗時操作

? ? System.out.println("onStart");

? ? try {

? ? Thread.sleep(20000);

? ? } catch (InterruptedException e) {

? ? e.printStackTrace();

? ? }

? ? System.out.println("睡眠結束");

? ? }


? ? @Override

? ? public IBinder onBind(Intent intent) {

? ? return null;

? ? }

? ? }

2.IntentService:

? ? package com.zhf.service;


? ? import Android.app.IntentService;

? ? import Android.content.Intent;


? ? public class MyIntentService extends IntentService {


? ? public MyIntentService() {

? ? super("yyyyyyyyyyy");

? ? }


? ? @Override

? ? protected void onHandleIntent(Intent intent) {

? ? // 經測試郑兴,IntentService里面是可以進行耗時的操作的

? ? //IntentService使用隊列的方式將請求的Intent加入隊列,然后開啟一個worker thread(線程)來處理隊列中的Intent

? ? //對于異步的startService請求贝乎,IntentService會處理完成一個之后再處理第二個

? ? System.out.println("onStart");

? ? try {

? ? Thread.sleep(20000);

? ? } catch (InterruptedException e) {

? ? e.printStackTrace();

? ? }

? ? System.out.println("睡眠結束");

? ? }

? ? }

測試主程序:

? ? package com.zhf.service;


? ? import Android.app.Activity;

? ? import Android.content.Intent;

? ? import Android.os.Bundle;


? ? public class ServiceDemoActivity extends Activity {

? ? /** Called when the activity is first created. */

? ? @Override

? ? public void onCreate(Bundle savedInstanceState) {

? ? super.onCreate(savedInstanceState);

? ? setContentView(R.layout.main);

? ? startService(new Intent(this,MyService.class));//主界面阻塞情连,最終會出現(xiàn)Application not responding

? ? //連續(xù)兩次啟動IntentService,會發(fā)現(xiàn)應用程序不會阻塞览效,而且最重的是第二次的請求會再第一個請求結束之后運行(這個證實了IntentService采用單獨的線程每次只從隊列中拿出一個請求進行處理)

? ? startService(new Intent(this,MyIntentService.class));

? ? startService(new Intent(this,MyIntentService.class));

? ? }

? ? }

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末却舀,一起剝皮案震驚了整個濱河市虫几,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌挽拔,老刑警劉巖辆脸,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異螃诅,居然都是意外死亡啡氢,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門术裸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來倘是,“玉大人,你說我怎么就攤上這事袭艺〔笳福” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵猾编,是天一觀的道長门坷。 經常有香客問我,道長袍镀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任冻晤,我火速辦了婚禮苇羡,結果婚禮上,老公的妹妹穿的比我還像新娘鼻弧。我一直安慰自己设江,他們只是感情好,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布攘轩。 她就那樣靜靜地躺著叉存,像睡著了一般。 火紅的嫁衣襯著肌膚如雪度帮。 梳的紋絲不亂的頭發(fā)上歼捏,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機與錄音笨篷,去河邊找鬼瞳秽。 笑死,一個胖子當著我的面吹牛率翅,可吹牛的內容都是我干的练俐。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼冕臭,長吁一口氣:“原來是場噩夢啊……” “哼腺晾!你這毒婦竟也來了燕锥?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤悯蝉,失蹤者是張志新(化名)和其女友劉穎归形,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泉粉,經...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡连霉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了嗡靡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跺撼。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖讨彼,靈堂內的尸體忽然破棺而出歉井,到底是詐尸還是另有隱情,我是刑警寧澤哈误,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布哩至,位于F島的核電站,受9級特大地震影響蜜自,放射性物質發(fā)生泄漏菩貌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一重荠、第九天 我趴在偏房一處隱蔽的房頂上張望箭阶。 院中可真熱鬧,春花似錦戈鲁、人聲如沸仇参。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诈乒。三九已至,卻和暖如春婆芦,著一層夾襖步出監(jiān)牢的瞬間怕磨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工消约, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留癌压,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓荆陆,卻偏偏與公主長得像滩届,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348