Android从入门到放弃——四大组件之Service(1)

今天我们介绍一下Android四大组件之一的Service

什么是Service:

Android的四大组件之一,是Android的一种机制,被设计来的目录是为了处理一些后台数据。通常情况下它是运行在主线程的,所以不要直接在service里面做耗时操作。耗时任务同样需要使用thread来处理。

Service分类:我们通过service运行的地方可以分为本地和远程服务。

本地服务:使用频率比较多,依附于主进程,可以节约一些资源。使用比较简单。缺点就是主进程结束之后也会跟着结束。

远程服务:很少使用,会单独开启一个进程。因此主进程结束后并不会对它有影响。缺点是使用相对复杂。主要是提供一些系统服务。

因为远程服务比较复杂,今天先将本地服务的用法,后面一章再专门讲远程服务。

我们先来看看官方给出的Service的生命周期图:

可以看到它的生命周期会根据我们启动方式分2种情况,startService和bindService。那么我们就来分别看看这2种方式有什么区别

startService:直接启动Service,启动后无法跟它进行交互。适合用来做一些不需要和界面有任何交互的数据处理。

bindService:绑定service,绑定成功后可以获取到一个IBinder接口,这样就可以来跟service有一些交互。

再来看看生命周期,先看看startService:

首先创建一个Service,直接继承Service即可

MyService

class MyService : Service() {

    override fun onCreate() {
        super.onCreate()
        Log.d("ZLog MyService", "onCreate: ")
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.d("ZLog MyService", "onStartCommand: startId:$startId")
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onStart(intent: Intent?, startId: Int) {
        super.onStart(intent, startId)
        Log.d("ZLog MyService", "onStart: startId:$startId")
    }

    override fun onBind(intent: Intent): IBinder {
        Log.d("ZLog MyService", "onBind: $intent")
        return MyBinder()
    }

    override fun onUnbind(intent: Intent?): Boolean {
        Log.d("ZLog MyService", "onUnbind: ")
        return super.onUnbind(intent)
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d("ZLog MyService", "onDestroy: ")
    }

    private class MyBinder : Binder() {

    }
}

Manifest.xml配置

<service
   android:name=".MyService"
   android:enabled="true" />

activity中启动服务的代码:

        acMainBtStart.setOnClickListener {
            startService(myServiceIntent)
        }

        acMainBtStop.setOnClickListener {
            stopService(myServiceIntent)
        }

界面就2个按钮,一个开始,一个停止

按下启动服务的按钮后按照官方的流程打印了,其中的onStart方法现在文档提示已经过时不推荐使用了。

这个方法是以前启动时会调用的方法。

那么如果我们现在反复的按下启动服务会怎么样呢?

大家可以看到,我又点击了3次,看到onCreate方法并没有重复的打印,只是onStartCommand在重复的调用,并且startId在递增,说明我们的Service并没有重复的创建,类似单例模式,只是每次启动系统会给我们一个计数器。

现在按下停止服务:

可以看到只有一个onDestroy被调用。这个时候再按下停止是没有任何反应了。意思是我们可以多次的调用启动同一个service,只会创建一个。停止服务只需要调用一次就可以了。

下面我们来看一下bindService的流程:

启动服务的activity:

    private lateinit var myServiceIntent: Intent

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        myServiceIntent = Intent(this, MyService::class.java)
        acMainBtStart.setOnClickListener {
            bindService(myServiceIntent, conn, Context.BIND_AUTO_CREATE)
        }

        acMainBtStop.setOnClickListener {
            unbindService(conn)
        }
    }

    private val conn = object : ServiceConnection {
        override fun onServiceDisconnected(name: ComponentName?) {
            Log.d("ZLog MainActivity", "onServiceDisconnected: $name")
        }

        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            Log.d("ZLog MainActivity", "onServiceConnected name:$name  service:$service")
        }
}

Service不用修改,来看看运行的效果:

我们启动之后打印了onCreate和onBind,还记得刚刚说bindService的特点就是可以拿到一个Ibinder,就是在onBind这个方法中返回的。

    override fun onBind(intent: Intent): IBinder {
        Log.d("ZLog MyService", "onBind: $intent")
        return MyBinder()
    }

我们返回了一个MyBinder,在这里定义了一个内部类:

    private class MyBinder : Binder() {

    }

目前这里没有任何方法,它就是我们可以在activity中和服务端通讯的媒介了。

它继承自Binder,这个是系统提供的一个Ibinder子类,内部 已经帮我们实现了很多方法。所以我们直接继承它就好了。那么我们在哪里获取这个Binder呢?

在activity中我们调用bindService方法的时候,第二个参数是一个ServiceConnection,这个接口有2个方法,看名字就知道一个是和服务连接上的时候被调用的(onServiceConnected),一个是连接被断开的时候调用的(onServiceDisconected)。onServiceConnected的第二个参数是Ibinder,就是我们Service中onBind返回的接口。所以我们在这里就可以通过这个Ibinder强转成MyBinder类,从而实现和服务通讯的操作。

我们同样试试反复的点击bindService看看

会发现点击之后没有任何方法被回调,所以我们的bindService只能调用一次。

再来看看unbindService:

可以看到首先调用了onUnbind,然后onDestroy被调用。注意:这里在activity中ServiceConnection中的onServiceDisconnected并没有被调用,因为我们手动刁永刚unbindService的时候是属于主动断开,并不会调用onServiceDisconnected,onServiceDisconnected方法是在服务如果被意外杀掉的时候才会被调用。

官方文档的意思是只有到启动service的进程已经崩溃或被杀死时才会调用到。

好了,到这里service的一些基本用法就差不多介绍完了。后面一章我们重点讲解远程Service和AIDL相关内容。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值