Android四大组件之Service

来源:互联网 发布:单片机软件原理 编辑:程序博客网 时间:2024/05/22 20:28

一、Service简介

Service是Android程序中四大基础组件之一,它和Activity一样都是Context的子类,只不过它没有UI界面,是在后台运行的组件。Service是Android中实现程序后台运行的解决方案,它非常适用于去执行那些不需要和用户交互而且还要求长期运行的任务。Service默认并不会运行在子线程中,它也不运行在一个独立的进程中,它同样执行在UI线程中,因此,不要在Service中执行耗时的操作,除非你在Service中创建了子线程来完成耗时操作。

二、Service种类

按运行地点分类:

这里写图片描述

按运行类型分类:

这里写图片描述

按使用方式分类:

这里写图片描述

三、Service生命周期

这里写图片描述

OnCreate()

系统在service第一次创建时执行此方法,来执行只运行一次的初始化工作。如果service已经运行,这个方法不会被调用。

onStartCommand()

每次客户端调用startService()方法启动该Service都会回调该方法(多次调用)。一旦这个方法执行,service就启动并且在后台长期运行。通过调用stopSelf()或stopService()来停止服务。

OnBind()

当组件调用bindService()想要绑定到service时(比如想要执行进程间通讯)系统调用此方法(一次调用,一旦绑定后,下次再调用bindService()不会回调该方法)。在你的实现中,你必须提供一个返回一个IBinder来以使客户端能够使用它与service通讯,你必须总是实现这个方法,但是如果你不允许绑定,那么你应返回null。

OnUnbind()

当前组件调用unbindService(),想要解除与service的绑定时系统调用此方法(一次调用,一旦解除绑定后,下次再调用unbindService()会抛出异常)。

OnDestory()

系统在service不再被使用并要销毁时调用此方法(一次调用).service应在此方法中释放资源,比如线程,已注册的侦听器,接收器等等.这是service收到的最后一个调用。

下面介绍三种不同情况下Service的生命周期情况。

1.startService / stopService

生命周期顺序:onCreate->onStartCommand->onDestroy

如果一个Service被某个Activity 调用 Context.startService方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行,直到被调stopService,或自身的stopSelf方法。当然如果系统资源不足,android系统也可能结束服务,还有一种方法可以关闭服务,在设置中,通过应用->找到自己应用->停止。

注意点:
①第一次 startService 会触发 onCreate 和 onStartCommand,以后在服务运行过程中,每次 startService 都只会触发 onStartCommand
②不论 startService 多少次,stopService 一次就会停止服务

2.bindService / unbindService

生命周期顺序:onCreate->onBind->onUnBind->onDestroy

如果一个Service在某个Activity中被调用bindService方法启动,不论bindService被调用几次,Service的onCreate方法只会执行一次,同时onStartCommand方法始终不会调用。

当建立连接后,Service会一直运行,除非调用unbindService来接触绑定、断开连接或调用该Service的Context不存在了(如Activity被Finish——即通过bindService启动的Service的生命周期依附于启动它的Context),系统在这时会自动停止该Service。

注意点:
第一次 bindService 会触发 onCreate 和 onBind,以后在服务运行过程中,每次bindService 都不会触发任何回调

3.混合型(上面两种方式的交互)

当一个Service在被启动(startService)的同时又被绑定(bindService),该Service将会一直在后台运行,并且不管调用几次,onCreate方法始终只会调用一次,onStartCommand的调用次数与startService调用的次数一致(使用bindService方法不会调用onStartCommand)。同时,调用unBindService将不会停止Service,必须调用stopService或Service自身的stopSelf来停止服务。

在什么情况下使用 startService 或 bindService 或 同时使用startService 和 bindService?

① 如果你只是想要启动一个后台服务长期进行某项任务那么使用 startService 便可以了。

② 如果你想要与正在运行的 Service 取得联系,那么有两种方法,一种是使用broadcast ,另外是使用 bindService ,前者的缺点是如果交流较为频繁,容易造成性能上的问题,并且 BroadcastReceiver 本身执行代码的时间是很短的(也许执行到一半,后面的代码便不会执行),而后者则没有这些问题,因此我们肯定选择使用 bindService(这个时候你便同时在使用 startService 和 bindService 了,这在Activity 中更新 Service 的某些运行状态是相当有用的)。

③ 如果你的服务只是公开一个远程接口,供连接上的客服端(android 的 Service是C/S架构)远程调用执行方法。这个时候你可以不让服务一开始就运行,而只用bindService ,这样在第一次 bindService 的时候才会创建服务的实例运行它,这会节约很多系统资源,特别是如果你的服务是Remote Service,那么该效果会越明显(当然在 Service 创建的时候会花去一定时间,你应当注意到这点)。

四、Service的几种典型使用实例

1.不可交互的后台服务

不可交互的后台服务即是普通的Service,通过startService()方式开启。Service的生命周期很简单,分别为onCreate、onStartCommand、onDestroy这三个。

创建服务类:

public class BackService extends Service {    private Thread mThread;    @Override    public void onCreate() {        super.onCreate();    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        System.out.println("onBind");        return null;    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        //执行耗时操作        mThread = new Thread() {        @Override        public void run() {            try {                while (true) {                    //等待停止线程                    if (this.isInterrupted()) {                        throw new InterruptedException();                    }                    //耗时操作。                    System.out.println("执行耗时操作");                }            } catch (InterruptedException e) {                e.printStackTrace();            }        }    };    mThread.start();        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        super.onDestroy();        //停止线程        mThread.interrupt();    }}

配置服务:

<service android:name=".BackService"></service>

如果想配置成远程服务,加如下代码:

android:process="remote"

配置好Service类,只需要在前台,调用startService()方法,就会启动耗时操作。

注意:
①不运行在一个独立的进程中,它同样执行在UI线程中,因此,在Service中创建了子线程来完成耗时操作

②当Service关闭后,如果在onDestory()方法中不关闭线程,你会发现我们的子线程进行的耗时操作是一直存在的,此时关闭该子线程的方法需要直接关闭该应用程序。因此,在onDestory()方法中要进行必要的清理工作。

2.可交互的后台服务

可交互的后台服务是指前台页面可以调用后台服务的方法,通过bindService()方式开启。Service的生命周期很简单,分别为onCreate、onBind、onUnBind、onDestroy这四个。可交互的后台服务实现步骤是和不可交互的后台服务实现步骤是一样的,区别在于启动的方式和获得Service的代理对象。

创建服务类
和普通Service不同在于这里返回一个代理对象,返回给前台进行获取,即前台可以获取该代理对象执行后台服务的方法

public class BackService extends Service {    @Override    public void onCreate() {        super.onCreate();    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        //返回MyBinder对象        return new MyBinder();    }    //需要返回给前台的Binder类    class MyBinder extends Binder {        public void showTip(){            System.out.println("我是来此服务的提示");        }    }    @Override    public void onDestroy() {        super.onDestroy();    }}

前台调用
通过以下方式绑定服务:

bindService(mIntent,con,BIND_AUTO_CREATE);

其中第二个参数:

private ServiceConnection con = new ServiceConnection() {    @Override    public void onServiceConnected(ComponentName name, IBinder service) {        BackService.MyBinder myBinder = (BackService.MyBinder) service;        myBinder.showTip();    }    @Override    public void onServiceDisconnected(ComponentName name) {    }};

当建立绑定后,onServiceConnected中的service便是Service类中onBind的返回值。如此便可以调用后台服务类的方法,实现交互。

当调用unbindService()停止服务,同时要在onDestory()方法中做好清理工作。

注意:通过bindService启动的Service的生命周期依附于启动它的Context。因此当前台调用bindService的Context销毁后,那么服务会自动停止。

3.混合型后台服务

将上面两种启动方式结合起来就是混合性交互的后台服务了,即可以单独运行后台服务,也可以运行后台服务中提供的方法,其完整的生命周期是:onCreate->onStartCommand->onBind->onUnBind->onDestroy

原创粉丝点击