Android之Service總結(jié)

轉(zhuǎn)載注明出處:http://www.reibang.com/p/a1d3d9693e91

1. 簡介

與前一篇Android之Activity總結(jié)是同一系列的文章专酗,是自己在學(xué)習(xí)和研發(fā)過程中,對Service的一些知識點的總結(jié)乡话,匯總得到這篇文章。

這篇文章會從Service的一些小知識點,延伸到Android中幾種常用進程間通信方法锦募。

2. 進程

Service是一種不提供用戶交互頁面但是可以在后臺長時間運行的組件虑瀑,可以通過在AndroidManifest.xml設(shè)置Service的android:process=":remote"屬性,讓Service運行另一個進程中敌厘,也就是說台猴,雖然你是在當(dāng)前應(yīng)用啟動的這個Service,但是這個Service和這個應(yīng)用并不是同一個進程。

四大組件都支持android:process=":remote"這個屬性饱狂。

因為Service可以運行在不同的進程曹步,這里說一下Android中幾種進程的優(yōu)先級,當(dāng)系統(tǒng)內(nèi)存不足時候休讳,系統(tǒng)會從優(yōu)先級低的進程開始回收箭窜,下面根據(jù)優(yōu)先級由高到低列出Android中幾種進程。

  • 前臺進程衍腥,當(dāng)前用戶操作所需要的進程

    • 用戶正在交互的Activity(Activity執(zhí)行了onResume方法)
    • 與正在交互的Activity綁定的Service
    • 設(shè)置為前臺權(quán)限的Service(Service調(diào)用startForeground()方法)
    • 正在執(zhí)行某些生命周期回調(diào)的Service磺樱,onCreate()、onStart()婆咸、onDestroy()
    • 正在執(zhí)行onReceive()的BroadcastReceiver

    這種進程基本不會被回收竹捉,只有當(dāng)內(nèi)存不足以支持前臺進程同時運行時候,系統(tǒng)才回回收它們尚骄,主要關(guān)注前三個块差。

  • 可見進程,沒有與用戶交互所必須的組件倔丈,但是在屏幕上仍然可見其內(nèi)容的進程

    • 調(diào)用了onPause()方法但仍對用戶可見的Activity
    • 與上面這種Activity綁定的Service
  • 服務(wù)進程憨闰,使用startService()啟動的Service且不屬于上面兩種類別進程的進程,雖然這個進程與用戶交互沒有直接關(guān)系需五,但是一般會在后臺執(zhí)行一些耗時操作鹉动,所以,只有當(dāng)內(nèi)存不足以維持所有前臺進程和可見進程同時運行宏邮,系統(tǒng)才回回收這個類別的進程泽示。

  • 后臺進程,對用戶不可見的Activity進程蜜氨,已調(diào)用了onStop()方法的Activity

  • 空進程械筛,不包含任何活動應(yīng)用組件的進程,保留這種進程唯一目的是作為緩存飒炎,縮短引用組件下次啟動時間埋哟。通常系統(tǒng)會最優(yōu)先回收這類進程。

此外郎汪,一個進程的級別可能會因為其他進程對它的依賴而有所提高赤赊,即進程A服務(wù)于進程B(B依賴A),那么A的進程級別至少是和B一樣高的怒竿。

3. Service配置

和其他組件(Activity/ContentProvider/BroadcastReceiver)一樣砍鸠,Service需要在Androidmanifest.xml中聲明。

<manifest ... >
  ...
  <application ... >
      <service android:name=".DemoService" />
      ...
  </application>
</manifest>

Service是運行在主線程中的耕驰,如果有什么耗時的操作爷辱,建議新建子線程去處理,避免阻塞主線程,降低ANR的風(fēng)險饭弓。

在另外一篇文章中Intent以及IntentFilter詳解提到過双饥,為了確保應(yīng)用的安全,不要為Service設(shè)置intent-filter弟断,因為如果使用隱式Intent去啟動Service時候咏花,手機里面那么多應(yīng)用,并不能確定哪一個Service響應(yīng)了這個Intent阀趴,所以在項目中盡量使用顯式Intent去啟動Service昏翰。在Android 5.0(API LEVEL 21)版本后的,如果傳入隱式Intent去調(diào)用bindService()方法刘急,系統(tǒng)會拋出異常棚菊。

可以通過設(shè)置android:exported=false來確保這個Service僅能在本應(yīng)用中使用。

4. 服務(wù)啟動方式

服務(wù)可以由其他組件啟動叔汁,而且如果用戶切換到其他應(yīng)用统求,這個服務(wù)可能會繼續(xù)在后臺執(zhí)行。到目前為止据块,Android中Service總共有三種啟動方式码邻。

  • Scheduled,可定時執(zhí)行的Service另假,是Android 5.0(API LEVEL 21)版本中新添加的一個Service像屋,名為JobService,繼承Service類浪谴,使用JobScheduler類調(diào)度它并且設(shè)置JobService運行的一些配置开睡。具體文檔可以參考JobScheduler因苹,如果你的應(yīng)用最低支持版本是21苟耻,官方建議使用JobService。
  • Started扶檐,通過startService()啟動的Service凶杖。通過這種方式啟動的Service會獨立的運行在后臺,即使啟動它的組件已經(jīng)銷毀了款筑。例如Activity A使用startService()啟動了Service B智蝠,過了會兒,Activity A執(zhí)行onDestroy()被銷毀了奈梳,如果Service B任務(wù)沒有執(zhí)行完畢,它仍然會在后臺執(zhí)行攘须。這種啟動方式啟動的Service需要主動調(diào)用StopService()停止服務(wù)漆撞。
  • Bound,通過bindService()啟動的Service。通過這種方式啟動Service時候浮驳,會返回一個客戶端交互接口悍汛,用戶可以通過這個接口與服務(wù)進行交互,如果這個服務(wù)是在另一個進程中至会,那么就實現(xiàn)了進程間通信离咐,也就是Messenger和AIDL,這個會是下篇文章的重點奉件。多個組件可以同時綁定同一個Service宵蛀,如果所有的組件都調(diào)用unbindService()解綁后,Service會被銷毀县貌。

startService和bindService可以同時使用

5. 主要方法

Service是一個抽象類糖埋,使用需要我們?nèi)崿F(xiàn)它的抽象方法onBind(),Service有且僅有這一個抽象方法窃这,還有一些其他的生命周期回調(diào)方法需要復(fù)寫幫助我們實現(xiàn)具體的功能瞳别。

  • onCreate(),在創(chuàng)建服務(wù)時候杭攻,可以在這個方法中執(zhí)行一些的初始化操作祟敛,它在onStartCommand()onBind()之前被調(diào)用。如果服務(wù)已經(jīng)存在兆解,調(diào)用startService()啟動服務(wù)時候這個方法不會調(diào)用馆铁,只會調(diào)用onStartCommand()方法。
  • onStartCommand()锅睛,其他組件通過startService()啟動服務(wù)時候會回調(diào)這個方法埠巨,這個方法執(zhí)行后,服務(wù)會啟動被在后臺運行现拒,需要調(diào)用stopSelf()或者stopService()停止服務(wù)辣垒。
  • onBind(),其他組件通過bindService()綁定服務(wù)時候會回調(diào)的方法印蔬,這是Service的一個抽象方法勋桶,如果客戶端需要與服務(wù)交互,需要在這個方法中返回一個IBinder實現(xiàn)類實例化對象侥猬,如果不想其他客戶端與服務(wù)綁定例驹,直接返回null。
  • onDestroy()退唠,當(dāng)服務(wù)不在還是用且即將被銷毀時鹃锈,會回調(diào)這個方法,可以在這個方法中做一些釋放資源操作瞧预,這是服務(wù)生命周期的最后一個回調(diào)屎债。

如果組件僅通過startService()啟動服務(wù)寨蹋,不論服務(wù)是否已經(jīng)啟動,都會回調(diào)onStartCommand()方法扔茅,而且服務(wù)會一直運行已旧,需要調(diào)用stopSelfstopService方法關(guān)閉服務(wù)。

如果組件僅通過bindService()綁定服務(wù)召娜,則服務(wù)只有在與組件綁定時候運行运褪,一旦所有的客戶端全部取消綁定unbindService,系統(tǒng)才會銷毀該服務(wù)玖瘸。

多次啟動同一個服務(wù)秸讹,只有在服務(wù)初次啟動時候會回調(diào)onCreate方法,但是每次都會回調(diào)onStartCommand雅倒,可以利用這個向服務(wù)傳遞一些信息璃诀。

onStartCommand()的回調(diào)是在UI主線程,如果有什么耗時的操作蔑匣,建議新啟線程去處理劣欢。

6. 啟動和關(guān)閉服務(wù)

啟動服務(wù):

  • JobScheduler.schedule()
  • startService(Intent)
  • bindService(Intent service, ServiceConnection conn, int flags)

關(guān)閉服務(wù):

  • JobScheduler.cancel()或者JobScheduler.cancelAll(),對應(yīng)JobScheduler.schedule()
  • Service自身的stopSelf()方法裁良,組件的stopService(Intent)方法凿将,對應(yīng)startService啟動方法
  • unbindService(ServiceConnection conn),對應(yīng)bindService

示例:

// 啟動服務(wù)
Intent intent = new Intent(this, DemoService.class);
startService(intent);

// 停止服務(wù)
stopService(intent)

// 綁定服務(wù)
ServiceConnection mConnection = ServiceConnection() { ... };
Intent intent = new Intent(this, DemoService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

// 解除綁定
unbindService(mConnection);

綁定服務(wù)bindService()第三個參數(shù)數(shù)值:

  • 0价脾,如果不想設(shè)置任何值牧抵,就設(shè)置成0
  • Context.BIND_AUTO_CREATE,綁定服務(wù)時候侨把,如果服務(wù)尚未創(chuàng)建犀变,服務(wù)會自動創(chuàng)建,在API LEVEL 14以前的版本不支持這個標(biāo)志秋柄,使用Context.BIND_WAIVE_PRIORITY可以達到同樣效果
  • Context.BIND_DEBUG_UNBIND获枝,通常用于Debug,在unbindService時候华匾,會將服務(wù)信息保存并打印出來映琳,這個標(biāo)記很容易造成內(nèi)存泄漏。
  • Context.BIND_NOT_FOREGROUND蜘拉,不會將被綁定的服務(wù)提升到前臺優(yōu)先級,但是這個服務(wù)也至少會和客戶端在內(nèi)存中優(yōu)先級是相同的有鹿。
  • Context.BIND_ABOVE_CLIENT旭旭,設(shè)置服務(wù)的進程優(yōu)先級高于客戶端的優(yōu)先級,只有當(dāng)需要服務(wù)晚于客戶端被銷毀這種情況才這樣設(shè)置葱跋。
  • Context.BIND_ALLOW_OOM_MANAGEMENT持寄,保持服務(wù)受默認的服務(wù)管理器管理源梭,當(dāng)內(nèi)存不足時候,會銷毀服務(wù)
  • Context.BIND_WAIVE_PRIORITY稍味,不會影響服務(wù)的進程優(yōu)先級废麻,像通用的應(yīng)用進程一樣將服務(wù)放在一個LRU表中
  • Context.BIND_IMPORTANT,標(biāo)識服務(wù)對客戶端是非常重要的模庐,會將服務(wù)提升至前臺進程優(yōu)先級烛愧,通常情況下,即時客戶端是前臺優(yōu)先級掂碱,服務(wù)最多也只能被提升至可見進程優(yōu)先級怜姿,
  • BIND_ADJUST_WITH_ACTIVITY,如果客戶端是Activity疼燥,服務(wù)優(yōu)先級的提高取決于Activity的進程優(yōu)先級沧卢,使用這個標(biāo)識后,會無視其他標(biāo)識醉者。

7. onStartCommand()返回值

onStartCommand()方法有一個int的返回值但狭,這個返回值標(biāo)識服務(wù)關(guān)閉后系統(tǒng)的后續(xù)操作。

返回值有以下幾種:

  • Service.START_STICKY撬即,啟動后的服務(wù)被殺死熟空,系統(tǒng)會自動重建服務(wù)并調(diào)用on onStartCommand(),但是不會傳入最后一個Intent(Service可能多次執(zhí)行onStartCommand)搞莺,會傳入一個空的Intent息罗,使用這個標(biāo)記要注意對Intent的判空處理。這個標(biāo)記適用于太依靠外界數(shù)據(jù)Intent才沧,在特定的時間迈喉,有明確的啟動和關(guān)閉的服務(wù),例如后臺運行的音樂播放温圆。
  • Service.START_NOT_STICKY挨摸,啟動后的服務(wù)被殺死,系統(tǒng)不會自動重新創(chuàng)建服務(wù)岁歉。這個標(biāo)記是最安全的得运,適用于依賴外界數(shù)據(jù)Intent的服務(wù),需要完全執(zhí)行的服務(wù)锅移。
  • Service.START_REDELIVER_INTENT熔掺,啟動后的服務(wù)被殺死,系統(tǒng)會重新創(chuàng)建服務(wù)并調(diào)用onStartCommand()非剃,同時會傳入最后一個Intent置逻。這個標(biāo)記適用于可恢復(fù)繼續(xù)執(zhí)行的任務(wù),比如說下載文件备绽。
  • Service.START_STICKY_COMPATIBILITY券坞,啟動后的服務(wù)被殺死鬓催,不能保證系統(tǒng)一定會重新創(chuàng)建Service。

8. Service生命周期

Service生命周期(從創(chuàng)建到銷毀)跟它被啟動的方式有關(guān)系恨锚,這里只介紹startServicebindService兩種啟動方法時候Service的生命周期宇驾。

  • startService啟動方式,其他組件用這種方式啟動服務(wù)猴伶,服務(wù)會在后臺一直運行课舍,只有服務(wù)調(diào)用本身的stopSelf()方法或者其他組件調(diào)用stopService()才能停止服務(wù)。
  • bindService啟動方式蜗顽,其他組件用這種方法綁定服務(wù)布卡,服務(wù)通過IBinder與客戶端通信,客戶端通過unbindService接觸對服務(wù)的綁定雇盖,當(dāng)沒有客戶端綁定到服務(wù)忿等,服務(wù)會被系統(tǒng)銷毀。

這兩種生命周期不是獨立的崔挖,組件可以同時用startService啟動服務(wù)同時用bindService綁定服務(wù)贸街,例如跨頁面的音樂播放器,就可以在多個頁面同時綁定同一個服務(wù)狸相,這種情況下需要調(diào)用stopService()或者服務(wù)本身的stopSelf()并且沒有客戶端綁定到服務(wù)薛匪,服務(wù)才會被銷毀。

Service生命周期圖

左圖是使用startService()所創(chuàng)建的服務(wù)的生命周期脓鹃,右圖是使用bindService()所創(chuàng)建的服務(wù)的生命周期逸尖。

9. 在前臺運行服務(wù)

服務(wù)可以通過startForeground來使服務(wù)變成前臺優(yōu)先級。

public final void startForeground(int id, Notification notification) {
    try {
        mActivityManager.setServiceForeground(
                new ComponentName(this, mClassName), mToken, id,
                notification, true);
    } catch (RemoteException ex) {
    }
}

第一個參數(shù)用于標(biāo)識你應(yīng)用中唯一的通知標(biāo)識id瘸右,不能設(shè)為0娇跟,最終會傳入NotificationManager.notify(int id, Notification notification)取消通知需要用到,第二個參數(shù)是通知具體內(nèi)容太颤。

前臺服務(wù)需要在狀態(tài)欄中添加通知苞俘,例如,將音樂播放器的服務(wù)設(shè)置為前臺服務(wù)龄章,狀態(tài)欄通知顯示正在播放的歌曲吃谣,并允許其他組件與其交互。

// 設(shè)置Notification屬性
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title), getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);

要將服務(wù)從前臺移除做裙,需要調(diào)用stopForeground(boolean removeNotification)岗憋,參數(shù)是一個布爾值,用來標(biāo)識服務(wù)從前臺服務(wù)移除時候菇用,是否需要移除狀態(tài)欄的通知澜驮。如果服務(wù)在前臺運行時候被停止,也會移除狀態(tài)欄的通知惋鸥。

10. 與服務(wù)通信

10.1 廣播

不多說杂穷,萬能的通信。

10.2 內(nèi)存共享

不多說卦绣,萬能的通信

10.3 本地數(shù)據(jù)共享

不多說耐量,萬能的通信,例如ContentProvider/SharePreference等等滤港。

10.4 startService()

使用這個方法啟動的服務(wù)廊蜒,再次調(diào)用startService()傳入Intent即可與服務(wù)通信,因為這種方式啟動的服務(wù)在完整的生命周期內(nèi)onCreate()只會執(zhí)行一次溅漾,而onStartCommand()會執(zhí)行多次山叮,我們再次調(diào)用startService()時候,可以在oonStartCommand()去處理添履。

10.5 bindService()

使用這種方法啟動的服務(wù)屁倔,組件有三種與服務(wù)通信的方式。

  • Service中實現(xiàn)IBinder
  • Messenger(AIDL的簡化版)
  • AIDL

下一篇文章具體介紹Messenger暮胧、AIDL锐借,因為它們是屬于Android進程間通信。

如果一個服務(wù)Service只需要在本應(yīng)用的進程中使用往衷,不提供給其他進程钞翔,推薦使用第一種方法。

使用示例:

Service:

/**
 * 本地服務(wù)
 * <br/>
 * 和啟動應(yīng)用屬于同一進程
 */
public class LocalService extends Service {
    /**
     * 自定的IBinder
     */
    private final IBinder mBinder = new LocalBinder();

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    /**
     * 提供給客戶端的方法
     *
     * @return
     */
    public String getServiceInfo() {
        return this.getPackageName() + " " + this.getClass().getSimpleName();
    }

    /**
     * 自定義的IBinder
     */
    public class LocalBinder extends Binder {
        public LocalService getService() {
            return LocalService.this;
        }
    }
}

Activity:

/**
 * 綁定本地服務(wù)的組件
 *
 * Created by KyoWang.
 */
public class BindLocalServiceActivity extends AppCompatActivity implements View.OnClickListener {

    private Button mShowServiceNameBtn;

    private LocalService mService;

    private boolean mBound = false;

    public ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            LocalService.LocalBinder binder = (LocalService.LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mBound = false;
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.a_bind_local_service);
        mShowServiceNameBtn = (Button) findViewById(R.id.bind_local_service_btn);
        mShowServiceNameBtn.setOnClickListener(this);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this, LocalService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if(mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if(id == R.id.bind_local_service_btn) {
            if(mBound) {
                String info = mService.getServiceInfo();
                Toast.makeText(BindLocalServiceActivity.this, info, Toast.LENGTH_SHORT).show();
            }
        }
    }
}

11. 服務(wù)長存后臺

關(guān)于網(wǎng)上通用的提升服務(wù)優(yōu)先級以保證服務(wù)長存后臺席舍,即保證服務(wù)不輕易被系統(tǒng)殺死的方法有以下幾種布轿。

  • 設(shè)置android:persistent="true",這是application的一個屬性来颤,官方都不建議使用汰扭。

    Whether or not the application should remain running at all times,
    "true" if it should, and "false" if not. 
    The default value is "false". 
    Applications should not normally set this flag; 
    persistence mode is intended only for certain system applications.
    
  • 設(shè)置android:priority優(yōu)先級脚曾,這個并不是Service的屬性东且。這個屬性是在intent-filter中設(shè)置的。官方解釋本讥,這個屬性只對活動和廣播有用珊泳,而且這個是接受Intent的優(yōu)先級,并不是在內(nèi)存中的優(yōu)先級拷沸,呵呵色查。

    android:priority
    The priority that should be given to the parent component with regard to 
    handling intents of the type described by the filter. 
    This attribute has meaning for both activities and broadcast receivers。
    
  • 在Service的onDestroy中發(fā)送廣播撞芍,然后重啟服務(wù)秧了,就目前我知道的,會出現(xiàn)Service的onDestroy不調(diào)用的情況序无。

  • startForeground验毡,這個上面提到過衡创,是通過Notification提升優(yōu)先級。

  • 設(shè)置onStartCommand()返回值晶通,讓服務(wù)被殺死后璃氢,系統(tǒng)重新創(chuàng)建服務(wù),上面提到過狮辽。

五個里面就兩個能稍微有點用一也,所以啊,網(wǎng)絡(luò)謠傳害死人喉脖。

12. IntentService

敲黑板時間椰苟,重點來了,官方強力推薦树叽。

前面提到兩點舆蝴。

  • 因為Service中幾個方法的回調(diào)都是在主線程中,如果使用Service執(zhí)行特別耗時的操作菱皆,建議單獨新建線程去操作须误,避免阻塞主線程(UI線程)
  • 啟動服務(wù)和停止服務(wù)是成對出現(xiàn)的,需要手動停止服務(wù)

IntentService完美的幫我們解決了這個問題仇轻,在內(nèi)部幫我們新建的線程京痢,不需要我們手動新建,執(zhí)行完畢任務(wù)后會自動關(guān)閉篷店。IntentService也是一個抽象類祭椰,里面有一個onHandleIntent(Intent intent)抽象方法,這個方法是在非UI線程調(diào)用的疲陕,在這里執(zhí)行耗時的操作方淤。

IntentService使用非UI線程逐一處理所有的啟動需求,它在內(nèi)部使用Handler蹄殃,將所有的請求放入隊列中携茂,依次處理,關(guān)于Handler可以看這篇文章诅岩,也就是說IntentService不能同時處理多個請求讳苦,如果不要求服務(wù)同時處理多個請求,可以考慮使用IntentService吩谦。

IntentService在內(nèi)部使用HandlerThread配合Handler來處理耗時操作鸳谜。

private final class ServiceHandler extends Handler {
    public ServiceHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        onHandleIntent((Intent)msg.obj);
        stopSelf(msg.arg1);
    }
}

public int onStartCommand(Intent intent, int flags, int startId) {
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

public void onStart(Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

注意msg.arg1它是請求的唯一標(biāo)識,每發(fā)送一個請求式廷,會生成一個唯一標(biāo)識咐扭,然后將請求放入Handler處理隊列中,從源代碼里面可以看見,在執(zhí)行完畢onHandleIntent方法后蝗肪,會執(zhí)行stopSelf來關(guān)閉本身袜爪,同時IntentService中onBind()方法默認返回null,這說明啟動IntetService的方式最好是用startService方法穗慕,這樣在服務(wù)執(zhí)行完畢后才會自動停止饿敲;如果使用bindService來啟動服務(wù)妻导,還是需要調(diào)用unbindService來解綁服務(wù)的逛绵,也需要復(fù)寫onBind()方法。

小盆宇:在onHandleIntent中倔韭,執(zhí)行onHandleIntent后緊接著執(zhí)行stopSelf(int startId)术浪,把服務(wù)就給停止了,那第一個請求執(zhí)行完畢服務(wù)就停止了寿酌,后續(xù)的請求怎么會執(zhí)行胰苏?

注意stopSelf(int startID)方法作用是在其參數(shù)startId跟最后啟動該service時生成的id相等時才會執(zhí)行停止服務(wù),當(dāng)有多個請求時候醇疼,如果發(fā)現(xiàn)當(dāng)前請求的startId不是最后一個請求的id硕并,那么不會停止服務(wù),所以只有當(dāng)最后一個請求執(zhí)行完畢后秧荆,才回停止服務(wù)倔毙。

13. 總結(jié)

在年前寫了出來,比Activity中的坑少了太多乙濒,希望對大家有幫助陕赃。下一篇是關(guān)于Android中進程通信Messenger/AIDL的,是本篇的補充颁股,但是也屬于單獨的知識點么库。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市甘有,隨后出現(xiàn)的幾起案子诉儒,更是在濱河造成了極大的恐慌,老刑警劉巖亏掀,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件忱反,死亡現(xiàn)場離奇詭異,居然都是意外死亡幌氮,警方通過查閱死者的電腦和手機缭受,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來该互,“玉大人米者,你說我怎么就攤上這事。” “怎么了蔓搞?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵胰丁,是天一觀的道長。 經(jīng)常有香客問我喂分,道長锦庸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任蒲祈,我火速辦了婚禮甘萧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘梆掸。我一直安慰自己扬卷,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布酸钦。 她就那樣靜靜地躺著怪得,像睡著了一般。 火紅的嫁衣襯著肌膚如雪卑硫。 梳的紋絲不亂的頭發(fā)上徒恋,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音欢伏,去河邊找鬼入挣。 笑死,一個胖子當(dāng)著我的面吹牛颜懊,可吹牛的內(nèi)容都是我干的财岔。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼河爹,長吁一口氣:“原來是場噩夢啊……” “哼匠璧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起咸这,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤夷恍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后媳维,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酿雪,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年侄刽,在試婚紗的時候發(fā)現(xiàn)自己被綠了指黎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡州丹,死狀恐怖醋安,靈堂內(nèi)的尸體忽然破棺而出杂彭,到底是詐尸還是另有隱情,我是刑警寧澤吓揪,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布亲怠,位于F島的核電站,受9級特大地震影響柠辞,放射性物質(zhì)發(fā)生泄漏团秽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一叭首、第九天 我趴在偏房一處隱蔽的房頂上張望习勤。 院中可真熱鬧,春花似錦放棒、人聲如沸姻报。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至损肛,卻和暖如春厢破,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背治拿。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工摩泪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人劫谅。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓见坑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親捏检。 傳聞我的和親對象是個殘疾皇子荞驴,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

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

  • 服務(wù)基本上分為兩種形式 啟動 當(dāng)應(yīng)用組件(如 Activity)通過調(diào)用 startService() 啟動服務(wù)時...
    pifoo閱讀 1,256評論 0 8
  • 前言:本文所寫的是博主的個人見解,如有錯誤或者不恰當(dāng)之處贯城,歡迎私信博主熊楼,加以改正!原文鏈接能犯,demo鏈接 Serv...
    PassersHowe閱讀 1,405評論 0 5
  • [文章內(nèi)容來自Developers] Service是一個可以在后臺執(zhí)行長時間運行操作而不提供用戶界面的應(yīng)用組件鲫骗。...
    岳小川閱讀 857評論 0 7
  • 上篇我們講解了Android中的5中等級的進程,分別是:前臺進程踩晶、可見進程执泰、服務(wù)進程、后臺進程渡蜻、空進程术吝。系統(tǒng)會按照...
    徐愛卿閱讀 3,843評論 6 33
  • 曾經(jīng)顿苇,我是一個視逛街為生命的人峭咒,我會為自己精挑細選每一件衣服,每一雙鞋子纪岁,每一件裝飾物凑队。中午經(jīng)常不睡覺,...
    慧慧媽媽66閱讀 708評論 2 6