Service 深度解析
通過android:process指定的遠(yuǎn)程服務(wù)是運(yùn)行在一個(gè)獨(dú)立的進(jìn)程里,比如說接入消息推送之類的,需要建立長連接。
以下默認(rèn)是local Service
-
服務(wù)適用于不需要和用戶交互,又需要長期運(yùn)行的任務(wù)。
-
服務(wù)的運(yùn)行不依賴于任何用戶界面,即使程序切換到了后臺(tái),服務(wù)仍能正常運(yùn)行。
-
服務(wù)并不是運(yùn)行在一個(gè)獨(dú)立的進(jìn)程中,而是依賴創(chuàng)建服務(wù)時(shí)所在的應(yīng)用程序進(jìn)程(默認(rèn)運(yùn)行在主線程中)。
-
服務(wù)并不會(huì)自動(dòng)創(chuàng)建線程,需要手動(dòng)開啟線程,才能執(zhí)行耗時(shí)操作。
-
每個(gè)服務(wù)只會(huì)存在一個(gè)實(shí)例,無論多次startService還是bindService獲取到的實(shí)例
-
服務(wù)啟動(dòng)了就會(huì)一直處于運(yùn)行狀態(tài),除非執(zhí)行stopService或者stopSelf (調(diào)用unbind不會(huì)停止service)
-
需要在AndroidManifest中聲明
既然服務(wù)和線程沒有任何關(guān)系,而且服務(wù)工作在主線程中,不能執(zhí)行耗時(shí)操作(無論是按鍵超時(shí)、服務(wù)超時(shí)、廣播超時(shí)都會(huì)造成ANR);那服務(wù)有啥用呢?讓服務(wù)執(zhí)行耗時(shí)操作需要手動(dòng)開啟線程,線程不也可以長時(shí)間運(yùn)行么?
官方解釋:
A service is simply a component that can run in the background, even when the user is not interacting with your application, so you should create a service only if that is what you need. If you must perform work outside of your main thread, but only while the user is interacting with your application, you should instead create a new thread.
If you create a Thread or an Executor in an Activity of your app, this leads to unpredictable results, since a simple screen orientation change will disrupt things, since the Activity will no longer be around when the Thread completes its task.You could use AsyncTask to handle this, but what if your app needs this Background Thread to be started from not just an Activity, but a notification or another component?
In these cases, Android Services are the right Android component to use to match up the Thread’s lifecycle with that of the Service’s lifecycle.
1、Thread 的運(yùn)行是獨(dú)立于Activity的,也就是說當(dāng)一個(gè)Activity被finish之后,如果你沒有主動(dòng)停止Thread或者Thread里的run方法沒有執(zhí)行完畢的話,Thread 也會(huì)一直執(zhí)行。在線程執(zhí)行完畢,我們可以手動(dòng)stopself讓service結(jié)束,避免浪費(fèi)資源。
2、當(dāng)Activity被finish之后,不再持有該Thread的引用,也就不能在不同的Activity中對(duì)同一Thread進(jìn)行控制。而我們可以在任何有Context的地方調(diào)用Context.startService、Context.stopService、Context.bindService,Context.unbindService 來操作service。
Android多線程編程
Android的單線程模型
1.不能阻塞UI線程。 所有耗時(shí)操作(網(wǎng)絡(luò)、數(shù)據(jù)庫、大文件等)都應(yīng)該放在子線程中操作
2.不能在UI線程之外訪問Android UI 。因?yàn)楦耈I的方法不是線程安全的(更新時(shí)會(huì)進(jìn)行線程檢查)
所以一般在子線程中執(zhí)行耗時(shí)操作,再回到主線程( UI線程 )更新UI。(一般通過Handler進(jìn)行操作)
Handle模型
Handle/Message/MessageQueue/Looper 實(shí)現(xiàn)線程間交互
1、每個(gè)線程都只有一個(gè)MessageQueue,一個(gè)Looper
2、handle.sendMessage()會(huì)將message放入當(dāng)前線程的Messagequeue中,等待執(zhí)行
3、looper.loop()遍歷MessageQueue中的每個(gè)message,執(zhí)行msg.target.handleMessage(),回調(diào)handler的handleMessage()
詳情請(qǐng)見:
服務(wù)的生命周期
-
onCreate() 服務(wù)創(chuàng)建的時(shí)候調(diào)用(只調(diào)用一次)
-
onStartCommand() 服務(wù)每次啟動(dòng)的時(shí)候調(diào)用(雖然每次startService都會(huì)調(diào)用一次,但每個(gè)服務(wù)都只會(huì)存在一個(gè)實(shí)例)
-
onDestroy() 服務(wù)銷毀時(shí)調(diào)用(如果startService & bindService,則要調(diào)用stopService & unbindService,才回調(diào)onDestroy)
執(zhí)行1-2 日志:onCreate -> onStartCommand -> onDestroy
執(zhí)行1-1-2 日志:onCreate -> onStartCommand -> onStartCommand -> onDestroy (onStartCommand會(huì)執(zhí)行多次)
執(zhí)行3-4 日志:onCreate -> onBind -> onServiceConnected -> onDestroy (直接bindService創(chuàng)建的服務(wù)不會(huì)執(zhí)行onStartCommand)
執(zhí)行1-3-4-2 日志:onCreate -> onStartCommand -> onBind -> onServiceConnected -> onDestroy (既執(zhí)行了startService,又執(zhí)行了bindService)
執(zhí)行4 日志:service not Registed exception (沒有bind,不能執(zhí)行unbind)
執(zhí)行1-4 日志:service not Registed exception
執(zhí)行1-3-4-4 日志:onCreate -> onStartCommand -> onBind -> onServiceConnected -> service not Registed exception (已經(jīng)unbind之后,未bind,也不能unbind)
在activity中執(zhí)行3,退出activity,報(bào)錯(cuò)has leaked ServiceConnection,會(huì)執(zhí)行onDestroy
在activity中執(zhí)行1,退出activity,不報(bào)錯(cuò),不會(huì)執(zhí)行onDestroy,服務(wù)啟動(dòng)了就會(huì)一直處于運(yùn)行狀態(tài),除非執(zhí)行stopService 或者 stopSelf
當(dāng)activity 和 service 綁定之后,就可以調(diào)用該服務(wù)中 binder 提供的方法了
4.unbindService
unbindService(serviceConnection) 復(fù)制代碼服務(wù)的使用
通過startService 和stopService只是啟動(dòng)和結(jié)束服務(wù),但是activity和service并沒有建立關(guān)聯(lián),activity并不能定點(diǎn)讓service干什么工作。
由bindService來建立 activity 和 service 之間的聯(lián)系,onBind返回的IBinder類向上轉(zhuǎn)型,為service中定義的Binder類,得到了Binder實(shí)例,就可以調(diào)用Binder中定義的方法。
var downloadBinder: MyService.DownLoadBinder? = nullval serviceConnection = object : ServiceConnection{override fun onServiceDisconnected(name: ComponentName?) {LogUtils.e(" onServiceDisconnected invoke!!!")}override fun onServiceConnected(name: ComponentName?, service: IBinder?) {LogUtils.e(" onServiceConnected invoke!!!")downloadBinder = service as MyService.DownLoadBinder? //向上轉(zhuǎn)型downloadBinder?.startDownLoad() //調(diào)用bind的方法downloadBinder?.getProgress()} } 復(fù)制代碼MyService.java
public class MyService extends Service {private DownLoadBinder mBinder = new DownLoadBinder();public static class DownLoadBinder extends Binder {public void startDownLoad() {Log.e("zhen", "startDownLoad");}public void getProgress() {Log.e("zhen", "getProgress");}}@Overridepublic void onCreate() {super.onCreate();Log.e("zhen", "onCreate");}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.e("zhen", "onStartCommand");return super.onStartCommand(intent, flags, startId);}@Nullable@Overridepublic IBinder onBind(Intent intent) {Log.e("zhen", "onBind");return mBinder;}@Overridepublic void onDestroy() {super.onDestroy();Log.e("zhen", "onDestroy");} } 復(fù)制代碼AndroidManifest中注冊(cè)
android:exported="true" 表示允許除當(dāng)前程序之外的其它程序訪問這個(gè)服務(wù),默認(rèn)為true
android:enabled="true" 表示啟動(dòng)這個(gè)服務(wù),默認(rèn)為true
<service android:name=".module.service.MyService"android:exported="true"android:enabled="true"/> 復(fù)制代碼轉(zhuǎn)載于:https://juejin.im/post/5b611a7d6fb9a04f87521e72
總結(jié)
以上是生活随笔為你收集整理的Service 深度解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 真正掌握vuex的使用方法(六)
- 下一篇: 模板代码复用的三种方式: 宏, 继承,