摘要:四大組件都支持這個(gè)屬性。到目前為止,中總共有三種啟動(dòng)方式。返回值方法有一個(gè)的返回值,這個(gè)返回值標(biāo)識(shí)服務(wù)關(guān)閉后系統(tǒng)的后續(xù)操作。,啟動(dòng)后的服務(wù)被殺死,不能保證系統(tǒng)一定會(huì)重新創(chuàng)建。
1. 簡(jiǎn)介
這篇文章會(huì)從Service的一些小知識(shí)點(diǎn),延伸到Android中幾種常用進(jìn)程間通信方法。
2. 進(jìn)程? ? ? ?Service是一種不提供用戶交互頁面但是可以在后臺(tái)長(zhǎng)時(shí)間運(yùn)行的組件,可以通過在AndroidManifest.xml設(shè)置Service的android:process=":remote"屬性,讓Service運(yùn)行另一個(gè)進(jìn)程中,也就是說,雖然你是在當(dāng)前應(yīng)用啟動(dòng)的這個(gè)Service,但是這個(gè)Service和這個(gè)應(yīng)用并不是同一個(gè)進(jìn)程。
四大組件都支持android:process=":remote"這個(gè)屬性。
因?yàn)镾ervice可以運(yùn)行在不同的進(jìn)程,這里說一下Android中幾種進(jìn)程的優(yōu)先級(jí),當(dāng)系統(tǒng)內(nèi)存不足時(shí)候,系統(tǒng)會(huì)從優(yōu)先級(jí)低的進(jìn)程開始回收,下面根據(jù)優(yōu)先級(jí)由高到低列出Android中幾種進(jìn)程。
前臺(tái)進(jìn)程,當(dāng)前用戶操作所需要的進(jìn)程
用戶正在交互的Activity(Activity執(zhí)行了onResume方法)
與正在交互的Activity綁定的Service
設(shè)置為前臺(tái)權(quán)限的Service(Service調(diào)用startForeground()方法)
正在執(zhí)行某些生命周期回調(diào)的Service,onCreate()、onStart()、onDestroy()
正在執(zhí)行onReceive()的BroadcastReceiver
這種進(jìn)程基本不會(huì)被回收,只有當(dāng)內(nèi)存不足以支持前臺(tái)進(jìn)程同時(shí)運(yùn)行時(shí)候,系統(tǒng)才回回收它們,主要關(guān)注前三個(gè)。
可見進(jìn)程,沒有與用戶交互所必須的組件,但是在屏幕上仍然可見其內(nèi)容的進(jìn)程
調(diào)用了onPause()方法但仍對(duì)用戶可見的Activity
與上面這種Activity綁定的Service
服務(wù)進(jìn)程,使用startService()啟動(dòng)的Service且不屬于上面兩種類別進(jìn)程的進(jìn)程,雖然這個(gè)進(jìn)程與用戶交互沒有直接關(guān)系,但是一般會(huì)在后臺(tái)執(zhí)行一些耗時(shí)操作,所以,只有當(dāng)內(nèi)存不足以維持所有前臺(tái)進(jìn)程和可見進(jìn)程同時(shí)運(yùn)行,系統(tǒng)才回回收這個(gè)類別的進(jìn)程。
后臺(tái)進(jìn)程,對(duì)用戶不可見的Activity進(jìn)程,已調(diào)用了onStop()方法的Activity
空進(jìn)程,不包含任何活動(dòng)應(yīng)用組件的進(jìn)程,保留這種進(jìn)程唯一目的是作為緩存,縮短引用組件下次啟動(dòng)時(shí)間。通常系統(tǒng)會(huì)最優(yōu)先回收這類進(jìn)程。
此外,一個(gè)進(jìn)程的級(jí)別可能會(huì)因?yàn)槠渌M(jìn)程對(duì)它的依賴而有所提高,即進(jìn)程A服務(wù)于進(jìn)程B(B依賴A),那么A的進(jìn)程級(jí)別至少是和B一樣高的。
3. Service配置和其他組件(Activity/ContentProvider/BroadcastReceiver)一樣,Service需要在Androidmanifest.xml中聲明。
... ...
Service是運(yùn)行在主線程中的,如果有什么耗時(shí)的操作,建議新建子線程去處理,避免阻塞主線程,降低ANR的風(fēng)險(xiǎn)。
? ? ? ?在另外一篇文章中Intent以及IntentFilter詳解提到過,為了確保應(yīng)用的安全,不要為Service設(shè)置intent-filter,因?yàn)槿绻褂秒[式Intent去啟動(dòng)Service時(shí)候,手機(jī)里面那么多應(yīng)用,并不能確定哪一個(gè)Service響應(yīng)了這個(gè)Intent,所以在項(xiàng)目中盡量使用顯式Intent去啟動(dòng)Service。在Android 5.0(API LEVEL 21)版本后的,如果傳入隱式Intent去調(diào)用bindService()方法,系統(tǒng)會(huì)拋出異常。
可以通過設(shè)置android:exported=false來確保這個(gè)Service僅能在本應(yīng)用中使用。
4. 服務(wù)啟動(dòng)方式服務(wù)可以由其他組件啟動(dòng),而且如果用戶切換到其他應(yīng)用,這個(gè)服務(wù)可能會(huì)繼續(xù)在后臺(tái)執(zhí)行。到目前為止,Android中Service總共有三種啟動(dòng)方式。
Scheduled,可定時(shí)執(zhí)行的Service,是Android 5.0(API LEVEL 21)版本中新添加的一個(gè)Service,名為JobService,繼承Service類,使用JobScheduler類調(diào)度它并且設(shè)置JobService運(yùn)行的一些配置。具體文檔可以參考JobScheduler,如果你的應(yīng)用最低支持版本是21,官方建議使用JobService。
Started,通過startService()啟動(dòng)的Service。通過這種方式啟動(dòng)的Service會(huì)獨(dú)立的運(yùn)行在后臺(tái),即使啟動(dòng)它的組件已經(jīng)銷毀了。例如Activity A使用startService()啟動(dòng)了Service B,過了會(huì)兒,Activity A執(zhí)行onDestroy()被銷毀了,如果Service B任務(wù)沒有執(zhí)行完畢,它仍然會(huì)在后臺(tái)執(zhí)行。這種啟動(dòng)方式啟動(dòng)的Service需要主動(dòng)調(diào)用StopService()停止服務(wù)。
Bound,通過bindService()啟動(dòng)的Service。通過這種方式啟動(dòng)Service時(shí)候,會(huì)返回一個(gè)客戶端交互接口,用戶可以通過這個(gè)接口與服務(wù)進(jìn)行交互,如果這個(gè)服務(wù)是在另一個(gè)進(jìn)程中,那么就實(shí)現(xiàn)了進(jìn)程間通信,也就是Messenger和AIDL,這個(gè)會(huì)是下篇文章的重點(diǎn)。多個(gè)組件可以同時(shí)綁定同一個(gè)Service,如果所有的組件都調(diào)用unbindService()解綁后,Service會(huì)被銷毀。
startService和bindService可以同時(shí)使用
5. 主要方法Service是一個(gè)抽象類,使用需要我們?nèi)?shí)現(xiàn)它的抽象方法onBind(),Service有且僅有這一個(gè)抽象方法,還有一些其他的生命周期回調(diào)方法需要復(fù)寫幫助我們實(shí)現(xiàn)具體的功能。
onCreate(),在創(chuàng)建服務(wù)時(shí)候,可以在這個(gè)方法中執(zhí)行一些的初始化操作,它在onStartCommand()和onBind()之前被調(diào)用。如果服務(wù)已經(jīng)存在,調(diào)用startService()啟動(dòng)服務(wù)時(shí)候這個(gè)方法不會(huì)調(diào)用,只會(huì)調(diào)用onStartCommand()方法。
onStartCommand(),其他組件通過startService()啟動(dòng)服務(wù)時(shí)候會(huì)回調(diào)這個(gè)方法,這個(gè)方法執(zhí)行后,服務(wù)會(huì)啟動(dòng)被在后臺(tái)運(yùn)行,需要調(diào)用stopSelf()或者stopService()停止服務(wù)。
onBind(),其他組件通過bindService()綁定服務(wù)時(shí)候會(huì)回調(diào)的方法,這是Service的一個(gè)抽象方法,如果客戶端需要與服務(wù)交互,需要在這個(gè)方法中返回一個(gè)IBinder實(shí)現(xiàn)類實(shí)例化對(duì)象,如果不想其他客戶端與服務(wù)綁定,直接返回null。
onDestroy(),當(dāng)服務(wù)不在還是用且即將被銷毀時(shí),會(huì)回調(diào)這個(gè)方法,可以在這個(gè)方法中做一些釋放資源操作,這是服務(wù)生命周期的最后一個(gè)回調(diào)。
如果組件僅通過startService()啟動(dòng)服務(wù),不論服務(wù)是否已經(jīng)啟動(dòng),都會(huì)回調(diào)onStartCommand()方法,而且服務(wù)會(huì)一直運(yùn)行,需要調(diào)用stopSelf和stopService方法關(guān)閉服務(wù)。
如果組件僅通過bindService()綁定服務(wù),則服務(wù)只有在與組件綁定時(shí)候運(yùn)行,一旦所有的客戶端全部取消綁定unbindService,系統(tǒng)才會(huì)銷毀該服務(wù)。
多次啟動(dòng)同一個(gè)服務(wù),只有在服務(wù)初次啟動(dòng)時(shí)候會(huì)回調(diào)onCreate方法,但是每次都會(huì)回調(diào)onStartCommand,可以利用這個(gè)向服務(wù)傳遞一些信息。
onStartCommand()的回調(diào)是在UI主線程,如果有什么耗時(shí)的操作,建議新啟線程去處理。
6. 啟動(dòng)和關(guān)閉服務(wù)啟動(dòng)服務(wù):
JobScheduler.schedule()
startService(Intent)
bindService(Intent service, ServiceConnection conn, int flags)
關(guān)閉服務(wù):
JobScheduler.cancel()或者JobScheduler.cancelAll(),對(duì)應(yīng)JobScheduler.schedule()
Service自身的stopSelf()方法,組件的stopService(Intent)方法,對(duì)應(yīng)startService啟動(dòng)方法
unbindService(ServiceConnection conn),對(duì)應(yīng)bindService
示例:
// 啟動(dòng)服務(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()第三個(gè)參數(shù)數(shù)值:
0,如果不想設(shè)置任何值,就設(shè)置成0
Context.BIND_AUTO_CREATE,綁定服務(wù)時(shí)候,如果服務(wù)尚未創(chuàng)建,服務(wù)會(huì)自動(dòng)創(chuàng)建,在API LEVEL 14以前的版本不支持這個(gè)標(biāo)志,使用Context.BIND_WAIVE_PRIORITY可以達(dá)到同樣效果
Context.BIND_DEBUG_UNBIND,通常用于Debug,在unbindService時(shí)候,會(huì)將服務(wù)信息保存并打印出來,這個(gè)標(biāo)記很容易造成內(nèi)存泄漏。
Context.BIND_NOT_FOREGROUND,不會(huì)將被綁定的服務(wù)提升到前臺(tái)優(yōu)先級(jí),但是這個(gè)服務(wù)也至少會(huì)和客戶端在內(nèi)存中優(yōu)先級(jí)是相同的。
Context.BIND_ABOVE_CLIENT,設(shè)置服務(wù)的進(jìn)程優(yōu)先級(jí)高于客戶端的優(yōu)先級(jí),只有當(dāng)需要服務(wù)晚于客戶端被銷毀這種情況才這樣設(shè)置。
Context.BIND_ALLOW_OOM_MANAGEMENT,保持服務(wù)受默認(rèn)的服務(wù)管理器管理,當(dāng)內(nèi)存不足時(shí)候,會(huì)銷毀服務(wù)
Context.BIND_WAIVE_PRIORITY,不會(huì)影響服務(wù)的進(jìn)程優(yōu)先級(jí),像通用的應(yīng)用進(jìn)程一樣將服務(wù)放在一個(gè)LRU表中
Context.BIND_IMPORTANT,標(biāo)識(shí)服務(wù)對(duì)客戶端是非常重要的,會(huì)將服務(wù)提升至前臺(tái)進(jìn)程優(yōu)先級(jí),通常情況下,即時(shí)客戶端是前臺(tái)優(yōu)先級(jí),服務(wù)最多也只能被提升至可見進(jìn)程優(yōu)先級(jí),
BIND_ADJUST_WITH_ACTIVITY,如果客戶端是Activity,服務(wù)優(yōu)先級(jí)的提高取決于Activity的進(jìn)程優(yōu)先級(jí),使用這個(gè)標(biāo)識(shí)后,會(huì)無視其他標(biāo)識(shí)。
7. onStartCommand()返回值onStartCommand()方法有一個(gè)int的返回值,這個(gè)返回值標(biāo)識(shí)服務(wù)關(guān)閉后系統(tǒng)的后續(xù)操作。
返回值有以下幾種:
Service.START_STICKY,啟動(dòng)后的服務(wù)被殺死,系統(tǒng)會(huì)自動(dòng)重建服務(wù)并調(diào)用on onStartCommand(),但是不會(huì)傳入最后一個(gè)Intent(Service可能多次執(zhí)行onStartCommand),會(huì)傳入一個(gè)空的Intent,使用這個(gè)標(biāo)記要注意對(duì)Intent的判空處理。這個(gè)標(biāo)記適用于太依靠外界數(shù)據(jù)Intent,在特定的時(shí)間,有明確的啟動(dòng)和關(guān)閉的服務(wù),例如后臺(tái)運(yùn)行的音樂播放。
Service.START_NOT_STICKY,啟動(dòng)后的服務(wù)被殺死,系統(tǒng)不會(huì)自動(dòng)重新創(chuàng)建服務(wù)。這個(gè)標(biāo)記是最安全的,適用于依賴外界數(shù)據(jù)Intent的服務(wù),需要完全執(zhí)行的服務(wù)。
Service.START_REDELIVER_INTENT,啟動(dòng)后的服務(wù)被殺死,系統(tǒng)會(huì)重新創(chuàng)建服務(wù)并調(diào)用onStartCommand(),同時(shí)會(huì)傳入最后一個(gè)Intent。這個(gè)標(biāo)記適用于可恢復(fù)繼續(xù)執(zhí)行的任務(wù),比如說下載文件。
Service.START_STICKY_COMPATIBILITY,啟動(dòng)后的服務(wù)被殺死,不能保證系統(tǒng)一定會(huì)重新創(chuàng)建Service。
8. Service生命周期Service生命周期(從創(chuàng)建到銷毀)跟它被啟動(dòng)的方式有關(guān)系,這里只介紹startService和bindService兩種啟動(dòng)方法時(shí)候Service的生命周期。
startService啟動(dòng)方式,其他組件用這種方式啟動(dòng)服務(wù),服務(wù)會(huì)在后臺(tái)一直運(yùn)行,只有服務(wù)調(diào)用本身的stopSelf()方法或者其他組件調(diào)用stopService()才能停止服務(wù)。
bindService啟動(dòng)方式,其他組件用這種方法綁定服務(wù),服務(wù)通過IBinder與客戶端通信,客戶端通過unbindService接觸對(duì)服務(wù)的綁定,當(dāng)沒有客戶端綁定到服務(wù),服務(wù)會(huì)被系統(tǒng)銷毀。
這兩種生命周期不是獨(dú)立的,組件可以同時(shí)用startService啟動(dòng)服務(wù)同時(shí)用bindService綁定服務(wù),例如跨頁面的音樂播放器,就可以在多個(gè)頁面同時(shí)綁定同一個(gè)服務(wù),這種情況下需要調(diào)用stopService()或者服務(wù)本身的stopSelf()并且沒有客戶端綁定到服務(wù),服務(wù)才會(huì)被銷毀。
左圖是使用startService()所創(chuàng)建的服務(wù)的生命周期,右圖是使用bindService()所創(chuàng)建的服務(wù)的生命周期。
9. 在前臺(tái)運(yùn)行服務(wù)服務(wù)可以通過startForeground來使服務(wù)變成前臺(tái)優(yōu)先級(jí)。
public final void startForeground(int id, Notification notification) { try { mActivityManager.setServiceForeground( new ComponentName(this, mClassName), mToken, id, notification, true); } catch (RemoteException ex) { } }
第一個(gè)參數(shù)用于標(biāo)識(shí)你應(yīng)用中唯一的通知標(biāo)識(shí)id,不能設(shè)為0,最終會(huì)傳入NotificationManager.notify(int id, Notification notification)取消通知需要用到,第二個(gè)參數(shù)是通知具體內(nèi)容。
前臺(tái)服務(wù)需要在狀態(tài)欄中添加通知,例如,將音樂播放器的服務(wù)設(shè)置為前臺(tái)服務(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ù)從前臺(tái)移除,需要調(diào)用stopForeground(boolean removeNotification),參數(shù)是一個(gè)布爾值,用來標(biāo)識(shí)服務(wù)從前臺(tái)服務(wù)移除時(shí)候,是否需要移除狀態(tài)欄的通知。如果服務(wù)在前臺(tái)運(yùn)行時(shí)候被停止,狀態(tài)欄的通知也會(huì)被移除。
10. 與服務(wù)通信 10.1 廣播不多說,萬能的通信。
10.2 本地?cái)?shù)據(jù)共享不多說,萬能的通信,例如ContentProvider/SharePreference等等。
10.3 startService()? ? ? ?使用這個(gè)方法啟動(dòng)的服務(wù),再次調(diào)用startService()傳入Intent即可與服務(wù)通信,因?yàn)檫@種方式啟動(dòng)的服務(wù)在完整的生命周期內(nèi)onCreate()只會(huì)執(zhí)行一次,而onStartCommand()會(huì)執(zhí)行多次,我們?cè)俅握{(diào)用startService()時(shí)候,可以在oonStartCommand()去處理。
10.4 bindService()使用這種方法啟動(dòng)的服務(wù),組件有三種與服務(wù)通信的方式。
Service中實(shí)現(xiàn)IBinder
Messenger(AIDL的簡(jiǎn)化版)
AIDL
下一篇文章具體介紹Messenger、AIDL,因?yàn)樗鼈兪菍儆贏ndroid進(jìn)程間通信。
如果一個(gè)服務(wù)Service只需要在本應(yīng)用的進(jìn)程中使用,不提供給其他進(jìn)程,推薦使用第一種方法。
使用示例:
Service:
/** * 本地服務(wù) *
* 和啟動(dòng)應(yīng)用屬于同一進(jìn)程 */ 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ù)長(zhǎng)存后臺(tái)
關(guān)于網(wǎng)上通用的提升服務(wù)優(yōu)先級(jí)以保證服務(wù)長(zhǎng)存后臺(tái),即保證服務(wù)不輕易被系統(tǒng)殺死的方法有以下幾種。
設(shè)置android:persistent="true",這是application的一個(gè)屬性,官方都不建議使用。
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)先級(jí),這個(gè)并不是Service的屬性。這個(gè)屬性是在intent-filter中設(shè)置的。官方解釋,這個(gè)屬性只對(duì)活動(dòng)和廣播有用,而且這個(gè)是接受Intent的優(yōu)先級(jí),并不是在內(nèi)存中的優(yōu)先級(jí),呵呵。
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ù),就目前我知道的,會(huì)出現(xiàn)Service的onDestroy不調(diào)用的情況。
startForeground,這個(gè)上面提到過,是通過Notification提升優(yōu)先級(jí)。
設(shè)置onStartCommand()返回值,讓服務(wù)被殺死后,系統(tǒng)重新創(chuàng)建服務(wù),上面提到過。
五個(gè)里面就兩個(gè)能稍微有點(diǎn)用,所以啊,網(wǎng)絡(luò)謠傳害死人。
12. IntentService敲黑板時(shí)間,重點(diǎn)來了,官方強(qiáng)力推薦。
前面提到兩點(diǎn)。
因?yàn)镾ervice中幾個(gè)方法的回調(diào)都是在主線程中,如果使用Service執(zhí)行特別耗時(shí)的操作,建議多帶帶新建線程去操作,避免阻塞主線程(UI線程)
啟動(dòng)服務(wù)和停止服務(wù)是成對(duì)出現(xiàn)的,需要手動(dòng)停止服務(wù)
? ? ? ?IntentService完美的幫我們解決了這個(gè)問題,在內(nèi)部幫我們新建的線程,不需要我們手動(dòng)新建,執(zhí)行完畢任務(wù)后會(huì)自動(dòng)關(guān)閉。IntentService也是一個(gè)抽象類,里面有一個(gè)onHandleIntent(Intent intent)抽象方法,這個(gè)方法是在非UI線程調(diào)用的,在這里執(zhí)行耗時(shí)的操作。
? ? ? ?IntentService使用非UI線程逐一處理所有的啟動(dòng)需求,它在內(nèi)部使用Handler,將所有的請(qǐng)求放入隊(duì)列中,依次處理,關(guān)于Handler可以看這篇文章,也就是說IntentService不能同時(shí)處理多個(gè)請(qǐng)求,如果不要求服務(wù)同時(shí)處理多個(gè)請(qǐng)求,可以考慮使用IntentService。
IntentService在內(nèi)部使用HandlerThread配合Handler來處理耗時(shí)操作。
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它是請(qǐng)求的唯一標(biāo)識(shí),每發(fā)送一個(gè)請(qǐng)求,會(huì)生成一個(gè)唯一標(biāo)識(shí),然后將請(qǐng)求放入Handler處理隊(duì)列中,從源代碼里面可以看見,在執(zhí)行完畢onHandleIntent方法后,會(huì)執(zhí)行stopSelf來關(guān)閉本身,同時(shí)IntentService中onBind()方法默認(rèn)返回null,這說明啟動(dòng)IntetService的方式最好是用startService方法,這樣在服務(wù)執(zhí)行完畢后才會(huì)自動(dòng)停止;如果使用bindService來啟動(dòng)服務(wù),還是需要調(diào)用unbindService來解綁服務(wù)的,也需要復(fù)寫onBind()方法。
小盆宇:在ServiceHandler類的handleMessage方法中,執(zhí)行onHandleIntent后緊接著執(zhí)行stopSelf(int startId),把服務(wù)就給停止了,那第一個(gè)請(qǐng)求執(zhí)行完畢服務(wù)就停止了,后續(xù)的請(qǐng)求怎么會(huì)執(zhí)行?
? ? ? ?注意stopSelf(int startID)方法作用是在其參數(shù)startId跟最后啟動(dòng)該service時(shí)生成的id相等時(shí)才會(huì)執(zhí)行停止服務(wù),當(dāng)有多個(gè)請(qǐng)求時(shí)候,如果發(fā)現(xiàn)當(dāng)前請(qǐng)求的startId不是最后一個(gè)請(qǐng)求的id,那么不會(huì)停止服務(wù),所以只有當(dāng)最后一個(gè)請(qǐng)求執(zhí)行完畢后,才會(huì)停止服務(wù)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/70544.html
摘要:但是,一定會(huì)被執(zhí)行,從而保證了廣播在死亡前一定會(huì)被注銷,從而防止內(nèi)存泄露。對(duì)于應(yīng)用內(nèi)廣播的動(dòng)態(tài)注冊(cè)非方式,回調(diào)中的返回值是 前言 BroadcastReceiver(廣播接收器),屬于Android四大組件之一 在Android開發(fā)中,BroadcastReceiver的應(yīng)用場(chǎng)景非常多 今天,我將詳細(xì)講解關(guān)于BroadcastReceiver的一切相關(guān)知識(shí) 目錄 showImg(...
閱讀 3979·2021-11-24 09:38
閱讀 1243·2021-10-19 11:42
閱讀 1840·2021-10-14 09:42
閱讀 2166·2019-08-30 15:44
閱讀 555·2019-08-30 14:04
閱讀 2901·2019-08-30 13:13
閱讀 1963·2019-08-30 12:51
閱讀 972·2019-08-30 11:22