android学习笔记 - service(kotlin实现)

Posted 我叫白小飞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android学习笔记 - service(kotlin实现)相关的知识,希望对你有一定的参考价值。

#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语言实现)
  1. 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")
    

  1. AndroidManifest.xml 文件中注册:
 <service android:name=".services.BookService"/>
  1. 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")
    




  1. 界面布局文件:
<?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()

demo地址

以上是关于android学习笔记 - service(kotlin实现)的主要内容,如果未能解决你的问题,请参考以下文章

Android学习笔记之Service

Android学习笔记:Android Service组件深入解析

Android Service学习笔记

学习笔记Android中Service通信

Android Service初步学习的笔记

Android学习笔记---使用Service模仿下载效果