#service從入門到放棄
微信公衆號:沒有
如果你覺得此文章對你有幫助,歡迎點贊
###service簡介
service和activity 、contentProvider、BroadcastReceiver並稱爲Android四大組件,其地位不言而喻,在使用中也確實舉足輕重。service的直接翻譯爲服務,它是一種在後臺執行長時間運行才最而沒有UI的應用組件。service可以理解爲沒有界面的activity,非常適合用於執行不需要交互界面且長期後臺運行的任務。service不能運行在獨立的進程中,需要依賴創建服務時所在的應用程序進程。服務器不會自動開啓工作線程,它和activity一樣,創建之後會創建一個主線程,工作線程需要我們手動創建服務可由其他應用組件啓動(如Activity),啓動方式後邊詳細講。
service基本上分爲兩種狀態:
啓動狀態:
如果一個service是通過startService() 方式啓動的,服務當前的狀態即爲“啓動”狀態。一旦啓動,服務即可在後臺長期運行,急事啓動該服務的組件已經被銷燬,也無任何影響,因爲服務此時不依賴任何組件,是獨立運行的,除非手動調用停止或者強行停止運行應用才能停止服務,已啓動的服務通常是執行單一操作,而且不會把結果返回給調用方。
綁定狀態:
如果一個service是通過bindService() 方式啓動的,則該服務是“綁定”狀態。綁定的服務提供了 客戶端-服務端的接口,允許組件與服務器進行交互、發送請求和獲取數據,並且可以利用IPC(進程通信機制)進行跨進程執行這些操作。此服務生命週期與綁定該服務的組件一致,組件銷燬後綁定的服務也會停止運行。
service創建及使用(啓動狀態)
- 1.定義一個service:
步驟如下:
- 創建一個類集成自android.app.Service,實現抽象方法onBind(),重寫onCreate()、onStart()()、onCommand()、onDestry();
注意
- 在AndroidManifest.xml清單文件中註冊該service;
具體實現:(使用kotlin語言實現)
- service代碼:
class BookService : Service() {
val TAG = "BookService"
override fun onBind(intent: Intent): IBinder? {
LogUtils.i(TAG,"onBind")
return null
}
override fun onCreate() {
super.onCreate()
LogUtils.i(TAG,"onCreate")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
LogUtils.i(TAG,"onStartCommand")
return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
super.onDestroy()
LogUtils.i(TAG,"onDestroy")
}
}
- AndroidManifest.xml 文件中註冊:
<service android:name=".services.BookService"/>
- activity中的代碼:
private val TAG = "MainActivity"
val RECEIVE_MESSAGE_CODE : Int = 0x0002
//客戶端的消息處理
class ClientHndler : Handler(){
override fun handleMessage(msg: Message?) {
super.handleMessage(msg)
LogUtils.i(TAG,"clientHndler")
when (msg?.what) {
RECEIVE_MESSAGE_CODE -> {
LogUtils.i(TAG,"這是來自服務端的問候:" + msg.obj)
}
else -> {
LogUtils.i(TAG,"未接收到服務端的問候!!!")
}
}
}
}
//初始化客戶端的messenger
val clientMessenger = Messenger(ClientHndler())
class MainActivity : AppCompatActivity(),ServiceConnection{
override fun onServiceDisconnected(p0: ComponentName?) {
//TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
LogUtils.i(TAG,"onServiceDisconnected")
}
private lateinit var movieService: MovieService
override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
//TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
LogUtils.i(TAG,"onServiceConnected")
var movieBinder = p1 as MovieService.MovieBinder
movieService = movieBinder.getMovieService()
}
class Conn : ServiceConnection{
val TAG = "Conn"
override fun onServiceDisconnected(p0: ComponentName?) {
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
LogUtils.i(TAG,"onServiceDisconnected")
}
lateinit var serviceMessenger: Messenger
override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
LogUtils.i(TAG,"onServiceConnected")
serviceMessenger = Messenger(p1)
}
}
val conn = Conn()
private var bookbinders = Intent()
private var movieBinders = Intent()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
LogUtils.i(TAG,"onCreate")
//直接啓動service
btn_start.setOnClickListener {
bookbinders.setClass(this,BookService().javaClass)
startService(bookbinders)
}
//停止service
btn_stop.setOnClickListener {
stopService(bookbinders)
}
//綁定service
btn_bind.setOnClickListener {
movieBinders.setClass(this,MovieService::class.java)
bindService(movieBinders,this,Service.BIND_AUTO_CREATE)
}
//解除綁定
btn_unbind.setOnClickListener {
unbindService(this)
}
//獲取數據
btn_getdata.setOnClickListener {
val count = movieService.movieName
println("從service獲取的count===$count")
}
//msg bind
btn_msg_bind.setOnClickListener {
var intent = Intent()
intent.setClass(this@MainActivity,MusicService::class.java)
bindService(intent,conn,Service.BIND_AUTO_CREATE)
}
//給service發送消息
btn_send_msg.setOnClickListener {
val message = Message.obtain(null, SEND_MESSAGE_CODE, 0, 0)
message.obj = "來自客戶端的問候!!!"
message.replyTo = clientMessenger
conn.serviceMessenger.send(message)
}
//取消綁定
btn_msg_unbind.setOnClickListener {
unbindService(conn)
}
}
override fun onStart() {
super.onStart()
LogUtils.i(TAG,"onStart")
}
override fun onRestart() {
super.onRestart()
LogUtils.i(TAG,"onRestart")
}
override fun onResume() {
super.onResume()
LogUtils.i(TAG,"onResume")
}
override fun onPause() {
super.onPause()
LogUtils.i(TAG,"onPause")
}
override fun onDestroy() {
super.onDestroy()
LogUtils.i(TAG,"onDestroy")
}
}
- 界面佈局文件:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:text="@string/main_start"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.16"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btn_bind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:text="@string/main_bind"
app:layout_constraintBottom_toTopOf="@+id/btn_start"
app:layout_constraintEnd_toEndOf="@+id/btn_start"
app:layout_constraintStart_toStartOf="@+id/btn_start" />
<Button
android:id="@+id/btn_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:text="@string/main_stop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.053"
app:layout_constraintStart_toEndOf="@+id/btn_start" />
<Button
android:id="@+id/btn_unbind"
android:layout_width="103dp"
android:layout_height="47dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:text="@string/main_unbind"
app:layout_constraintBottom_toTopOf="@+id/btn_stop"
app:layout_constraintEnd_toStartOf="@+id/btn_getdata"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="@+id/btn_stop" />
<Button
android:id="@+id/btn_getdata"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:text="獲取數據"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/btn_stop"
app:layout_constraintTop_toTopOf="@+id/btn_bind"
app:layout_constraintVertical_bias="0.0" />
<Button
android:id="@+id/btn_msg_bind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="112dp"
android:text="綁定service(msg)"
app:layout_constraintBottom_toBottomOf="parent"
tools:layout_editor_absoluteX="16dp" />
<Button
android:id="@+id/btn_msg_unbind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="取消綁定service(msg)"
app:layout_constraintBottom_toTopOf="@+id/btn_msg_bind"
tools:layout_editor_absoluteX="16dp" />
<Button
android:id="@+id/btn_send_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:text="發消息給service"
app:layout_constraintBottom_toTopOf="@+id/btn_unbind"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.46"
app:layout_constraintStart_toEndOf="@+id/btn_msg_bind" />
</android.support.constraint.ConstraintLayout>
接下來看一下service啓動的過程:
點擊“啓動service”按鈕:查看logcat:
09-25 14:03:09.307 16466-16466/com.xyd.servicedemo I/BookService:
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ main, com.xyd.servicedemo.services.BookService.onCreate(BookService.kt:18)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ args[0] = BookService
│ args[1] = onCreate
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ main, com.xyd.servicedemo.services.BookService.onStartCommand(BookService.kt:22)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ args[0] = BookService
│ args[1] = onStartCommand
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────
從log可以看到,當使用startService()方式啓動service時,service調用了onCreate 和 onStartCommand方法,service就被啓動了。startservice的啓動過程可以看這篇文章
然後我們再停止該service:
09-25 14:09:14.074 16466-16466/com.xyd.servicedemo I/BookService:
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ main, com.xyd.servicedemo.services.BookService.onDestroy(BookService.kt:28)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ args[0] = BookService
│ args[1] = onDestroy
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────
停止service調用的是:stopService(),當服務停止時,調用了service的onDestroy方法。
通過上邊的例子可以看到通過startservice啓動的service的生命週期,可以通過相應的方法管理service,並且啓動的service不依賴與啓動它的Activity,如果當前activity銷燬,service也不會被銷燬,還是會在後臺運行,感興趣的朋友可以試試。
service創建及使用(綁定狀態)
創建同上:具體步驟不寫了,直接上代碼吧!
service代碼:
class MovieService : Service(){
private val TAG = "MovieService"
private var movieBinder = MovieService.MovieBinder(this@MovieService)
private var isRun: Boolean = true
var count: Int = 0
var movieName: String = ""
private lateinit var myThread: Thread
override fun onCreate() {
super.onCreate()
LogUtils.i(TAG,"onBind")
myThread = object : Thread() {
override fun run() {
println("running from Thread: ${Thread.currentThread()}")
while (isRun){
try {
Thread.sleep(2000)
} catch (e: Exception) {
}
count++
movieName = "復仇者聯盟$count"
println(movieName)
}
}
}
myThread.start()
}
override fun onBind(p0: Intent?): IBinder {
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
LogUtils.i(TAG,"onBind")
return movieBinder
}
class MovieBinder(private val movieService: MovieService) : Binder(){
val TAG = "MovieBinder"
fun getMovieService() : MovieService{
LogUtils.i(TAG,"getMovieService")
return movieService
}
}
override fun unbindService(conn: ServiceConnection?) {
super.unbindService(conn)
LogUtils.i(TAG,"unbindService")
}
override fun onDestroy() {
super.onDestroy()
isRun = false
LogUtils.i(TAG,"onDestroy")
}
}
activity代碼已在上個例子中貼出,請查看。需要注意的是,與startservice方式不同的是,bindservice時需要創建一個ServiceConnection的實例,在bindservice時傳遞給service,該實例的作用是客戶端與服務端通訊的媒介,具體可看一下這篇文章
運行:直接點擊“綁定service”按鈕,查看log:
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ main, com.xyd.servicedemo.services.MovieService.onBind(MovieService.kt:45)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ args[0] = MovieService
│ args[1] = onBind
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────
09-25 14:32:52.109 16821-18011/com.xyd.servicedemo I/System.out: running from Thread: Thread[Thread-4,5,main]
09-25 14:32:52.109 16821-16821/com.xyd.servicedemo I/MainActivity:
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ main, com.xyd.servicedemo.MainActivity.onServiceConnected(MainActivity.kt:52)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ args[0] = MainActivity
│ args[1] = onServiceConnected
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────
09-25 14:32:52.110 16821-16821/com.xyd.servicedemo I/MovieService:
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ main, com.xyd.servicedemo.services.MovieService$MovieBinder.getMovieService(MovieService.kt:53)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ args[0] = MovieBinder
│ args[1] = getMovieService
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────
通過bindservice後,服務啓動,並且在客戶端的ServiceConnection中回掉了onServiceConnected()方法,表示客戶端已與服務端建立了連接,此時客戶端是可以和服務端單向通訊的。如果是綁定狀態的service,是依賴於啓動它的activity的,當該activity銷燬後,綁定的service也會被銷燬。
接下來看一下客戶端與服務端的通訊:
實例:客戶端的代碼一貼出,下邊看一下服務端的代碼
/**
* Created by zejian
* Time 2016/10/3.
* Description:Messenger服務端簡單實例,服務端進程
*/
//此變量定義在類外部就可以被全包訪問
val SEND_MESSAGE_CODE : Int = 0x0001
//服務端的消息處理
class InComingHandler : Handler(){
override fun handleMessage(msg: Message?) {
super.handleMessage(msg)
if (msg != null) {
when (msg.what) {
SEND_MESSAGE_CODE -> {
LogUtils.i("接受到客戶端消息:" + msg.obj)
//接受完客戶端的消息後需要返回給客戶端消息
//通過msg.replyTo 方法 獲取客戶端的messenger
val clientMessenger = msg.replyTo
//獲取到messenger之後,在通過客戶端的messenger給客戶端發送消息
val msg = Message.obtain()
msg.what = RECEIVE_MESSAGE_CODE
msg.obj = "hello client!!!"
Thread.sleep(3000)
clientMessenger.send(msg)
}
else -> {
LogUtils.i("未接受到客戶端消息")
}
}
}
}
}
private val mMessenger = Messenger(InComingHandler())
class MusicService : Service(){
override fun onBind(p0: Intent?): IBinder? {
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
return mMessenger.binder
}
}
主要的處理邏輯已在代碼中標明,請自行查看。
下面解決幾個問題:
- 1、Service的start和bind狀態有什麼區別?
首先第一個問題:
- Service的start和bind狀態的區別:首先是啓動方式不同,start是直接啓動,而bind是依賴於組件啓動的,其次是啓動的生命週期不同,start啓動時執行的是onCreate
、onStartCommand的方法,而bind啓動執行的是onBind方法。最後是start方式啓動的service可以獨立於組件運行,組件銷燬之後,service不會停止運行,而bind方式啓動的service則是依附於組件,組件銷燬後,service會被強制停止運行。
- 2、同一個Service,先startService,然後再bindService,如何把它停止掉?
這個問題可以通過例子來看:新建一個service,並且在清單文件中註冊:
class StartAndBindService : Service() {
val TAG = "StartAndBindService"
override fun onBind(intent: Intent): IBinder? {
LogUtils.i(TAG,"onBind")
return null
}
override fun onCreate() {
super.onCreate()
LogUtils.i(TAG,"onCreate")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
LogUtils.i(TAG,"onStartCommand")
return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
super.onDestroy()
LogUtils.i(TAG,"onDestroy")
}
}
然後在activity中新建兩個按鈕並設置點擊事件,一個按鈕是start,一個按鈕是bind,運行之後,先點擊start,然後點擊bind,會出現以下結果:
09-26 12:59:55.249 4898-4898/com.xyd.servicedemo I/StartAndBindService:
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ main, com.xyd.servicedemo.services.StartAndBindService.onCreate(StartAndBindService.kt:19)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ args[0] = StartAndBindService
│ args[1] = onCreate
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────
09-26 12:59:55.255 4898-4898/com.xyd.servicedemo I/StartAndBindService:
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ main, com.xyd.servicedemo.services.StartAndBindService.onStartCommand(StartAndBindService.kt:23)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ args[0] = StartAndBindService
│ args[1] = onStartCommand
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────
09-26 12:59:57.826 4898-4898/com.xyd.servicedemo I/StartAndBindService:
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ main, com.xyd.servicedemo.services.StartAndBindService.onBind(StartAndBindService.kt:13)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ args[0] = StartAndBindService
│ args[1] = onBind
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────
可以看出先啓動,然後在bind,兩種啓動都會執行,但是如果已這種方式啓動之後,調用stopservice,service不會被停止,而調用unbindservice後service纔會被停止,由此可見,service由start方式啓動,然後在調用bind之後,是先啓動,然後在和組件綁定,其實只是一個service,因爲onstart方法已被啓用,所以看不出來,其實在調用onbind的時候,不會再走onstart方法。
-
3、你有注意到Service的onStartCommand方法的返回值嗎?不同返回值有什麼區別?
這個問題可以看這篇文章,這個反之沒有研究過 -
4、Service的生命週期方法onCreate、onStart、onBind等運行在哪個線程?
這個可以在service中打log查看,咱們來看看:
09-26 13:34:43.271 5937-5937/com.xyd.servicedemo I/StartAndBindService:
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ main, com.xyd.servicedemo.services.StartAndBindService.onCreate(StartAndBindService.kt:25)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ args[0] = StartAndBindService
│ args[1] = onCreate運行在主線程
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────
09-26 13:34:43.273 5937-5937/com.xyd.servicedemo I/StartAndBindService:
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ main, com.xyd.servicedemo.services.StartAndBindService.onStartCommand(StartAndBindService.kt:41)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ args[0] = StartAndBindService
│ args[1] = onStartCommand運行在主線程
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ main, com.xyd.servicedemo.services.StartAndBindService.onStart(StartAndBindService.kt:34)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ args[0] = StartAndBindService
│ args[1] = onStart運行在主線程
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────
09-26 13:34:47.690 5937-5937/com.xyd.servicedemo I/StartAndBindService:
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ main, com.xyd.servicedemo.services.StartAndBindService.onDestroy(StartAndBindService.kt:51)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ args[0] = StartAndBindService
│ args[1] = onDestroy運行在主線程
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────
具體使用的判斷爲:Looper.getMainLooper() == Looper.myLooper()