AI智能
改变未来

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

[code]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配置

[code]<serviceandroid:name=\".MyService\"android:enabled=\"true\" />

activity中启动服务的代码:

[code]        acMainBtStart.setOnClickListener {startService(myServiceIntent)}acMainBtStop.setOnClickListener {stopService(myServiceIntent)}

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

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

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

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

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

现在按下停止服务:

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

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

启动服务的activity:

[code]    private lateinit var myServiceIntent: Intentoverride 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这个方法中返回的。

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

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

[code]    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) 打赏
未经允许不得转载:爱站程序员基地 » Android从入门到放弃——四大组件之Service(1)