Service 學(xué)習(xí)

Service 學(xué)習(xí)要點

1.Service概述

Service的主要作用是讓系統(tǒng)在后臺在后臺做一些不與用戶交互的操作(例如耗時操作:下載網(wǎng)絡(luò)資源,長期運行的操作:播放音樂)
Service與Thread的區(qū)別:(1)Service不是在一個獨立的進程中,它與我們的應(yīng)用程序在同一進程(process)中 (2)Service也不是一個線程,相反,它是運行在主線程的(即UI線程),因此若我們要在Service中進行耗時操作時,需要開啟一個子線程,在其中進行耗時操作,否則很容易出現(xiàn)ANR錯誤(Application Not Responding 程序無響應(yīng))

2.Service用法

ServiceTest.java如下:

public class ServiceTest extends Service {

private MyLocalBinder myLocalBinder=new
MyLocalBinder();

@Override
public void onCreate() {
    super.onCreate();
    Log.e("TAG","onCreate");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.e("TAG","onStartCommand");
    return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
    Log.e("TAG","onBind");
    return myLocalBinder;
}

@Override
public boolean onUnbind(Intent intent) {
    Log.e("TAG","onUnbind");
    return super.onUnbind(intent);
}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.e("TAG","onDestroy");
}

//對外提供的訪問方法
public void downLoad(){
    Log.e("downLoad","正在下載...");
}
public void undownLoad(){
    Log.e("downLoad","取消下載...");
}
class MyLocalBinder extends Binder{
    public ServiceTest getServiceTestInstance(){
        return ServiceTest.this;
    }
    //...這里也可以繼續(xù)寫方法對外提供
}

}

與Activity相似,使用Service也需要通過intent,不能忘記的是在使用Service前,需要在AndroidManifest.xml中進行聲明

啟動方式一:startService()

通過打印Service的生命周期,我們發(fā)現(xiàn)第一次啟動Service的時候,會執(zhí)行onCreate()和onStartCommand(),**
再次啟動時,只會執(zhí)行onStartCommand(),也就是說onCreate()只會在第一次啟動的時候進行初始化
**點擊“stopService”后,Service被銷毀,進入onDestroy()方法。不管我們啟動了多少次Service,只要我們在外部調(diào)用一次Context.stopService()或者在Service內(nèi)部調(diào)用stopSelf(),Service就會被銷毀

上面這種啟動方式的缺點:啟動完Service后,這個Service就在后臺運行了,同時也與啟動它的Activity失去了聯(lián)系,因為不能通過ServiceTest service = new ServiceTest()的方式啟動Service,因而我們的Activity中不能獲取到ServiceTest的實例。
為了解決與啟動Service的組件的通信能力,還有一個解決方案就是通過廣播的形式。我們在Activity中發(fā)出一些想用操作廣播,在Service中注冊該廣播,Service接收到該廣播信息后,完成相應(yīng)的功能。但是頻繁發(fā)送廣播比較消耗性能,同時,由于廣播接受者中的onReceive()中,不能執(zhí)行長時間的工作,時間超過后,可能就直接跳出了方法。因此,這種方案不是首選。

啟動方式二:bindService() Bound機制

通過bindService()方式第一次啟動后,會執(zhí)行onCreate()和onBind()方法,當(dāng)我們點擊“unBindService“時,走的是onUnbind()和onDestroy()方法。如果有另一個組件對同一個Service進行bindService()操作(也就是在bindService()中傳入不同的ServiceConnection,此時只會進入onBind()方法,即onCreate()只會在第一次啟動的時候進行初始化

總結(jié):可以看到,不管是通過哪種方式啟動Service,同一個Service在整個應(yīng)用程序中只有一個實例存在。區(qū)別:(1)兩種方式所走的生命周期是不一樣的(2)何時被銷毀:當(dāng)我們通過startService()啟動時,不管我們啟動了多少次Service,只要我們在外部調(diào)用一次Context.stopService()或者在Service內(nèi)部調(diào)用stopSelf(),Service就會被銷毀;而當(dāng)我們通過bindService()啟動時,前面我們多次啟動service后,當(dāng)所有客戶端發(fā)出unBindService(),這個Service將被系統(tǒng)銷毀。(3)當(dāng)Service即被startService()啟動也被bindService()啟動時,這種情況下,Service必須在既沒有任何activity關(guān)聯(lián)又停止的情況下,Service才會被銷毀。

3.IntentService

我們在第一部分談到,有時需要在service中進行耗時操作,此時就需要開啟一個子線程,而對于這種需求,Android提供了IntentService給用戶,intentservice內(nèi)部已經(jīng)幫我們開啟了線程,我們只需要實現(xiàn)它的onHandleIntent方法,在里面實現(xiàn)我們的功能即可,注:intentservice不能處理多個線程的請求,但是可以處理多個service的請求(此處求解?)

IntentService提供的功能:(1)所有請求處理完成后自動停止服務(wù)(2)提供了默認onBind()的實現(xiàn),直接返回null,意味著我們只能通過startService()的方式啟動IntentService

public class MyIntentService extends IntentService

{

public MyIntentService()

{
super("MyIntentService");
}

@Override
protected void onHandleIntent(Intent intent) {
    Log.e("MyIntentService","Thread is"+Thread.currentThread().getId());
}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.e("OnDestroy","OnDestroy");
}

}

使用時需注意兩點:首先要提供一個無參的構(gòu)造方法,里面調(diào)用父類的有參構(gòu)造方法,第二是實現(xiàn)onHandleIntent這個抽象方法。

4.前臺Service

Service默認都是在后臺默默運行的,用戶基本察覺不到有Service在運行。此時,Service的優(yōu)先級是比較低的,當(dāng)系統(tǒng)資源不足的時候,易被銷毀。因此,如果我們想讓用戶知道有Service在后臺運行,如音樂播放器,或者想讓Service一直保持運行狀態(tài),不容易被系統(tǒng)回收,此時,就可以考慮使用前臺Service。前臺Service是被認為是用戶已知的正在運行的服務(wù),當(dāng)系統(tǒng)需要釋放內(nèi)存時不會優(yōu)先殺掉該進程。
用法:

@Override

public void onCreate() {

    super.onCreate();
    Log.e("TAG","onCreate");
    Notification notification=new Notification(R.mipmap.ic_launcher,"前臺通知",System.currentTimeMillis());
    Intent intent=new Intent(this,MainActivity.class);
    PendingIntent pendingIntent=PendingIntent.getActivity(this,0,intent,0);
    notification.setLatestEventInfo(this, "通知標(biāo)題", "前臺Service內(nèi)容", pendingIntent);
    //設(shè)置到前臺運行,第一個參數(shù)為通知notification的唯一ID
    startForeground(1,notification);
}
(關(guān)于Notification在SDK23以后和SDK22之前用法不一樣,上面是SDK22以前的,下面是SDK23以后的)

Notification.Builder builder=new Notification.Builder(getApplication());
    builder.setContentInfo("補充內(nèi)容");
    builder.setContentText("主內(nèi)容區(qū)");
    builder.setContentTitle("通知標(biāo)題");
    builder.setSmallIcon(R.mipmap.ic_launcher);
    builder.setTicker("新消息");
    builder.setAutoCancel(true);
    builder.setWhen(System.currentTimeMillis());
    Intent intent = new Intent(getApplication(), MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(getApplication(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    builder.setContentIntent(pendingIntent);
    Notification notification = builder.build();

如果我們要移除這個前臺Service,只需要調(diào)用stopService()即可

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內(nèi)容