四大组件-服务 Service

定义

服务,Android四大组件之一,属于计算型组件

作用

提供需长期在后台运行的的服务

特点

无用户界面,在后台运行,生命周期长

生命周期

Service服务有两种启动的方式:

  • 通过调用startService()启动服务
  • 通过调用bindService()启动服务
  • 通过startService()启动服务的生命周期
    1.手动调用 startService() 方法
    2.onCreate()
    3.onStartCommand()
    4.手动调用 stopService() 方法
    5.onDestroy()

  • 通过bindService()启动服务的生命周期
    1.手动调用 bindService() 方法
    2.onCreeate()
    3.onBind()
    4.手动调用 unbindService() 方法
    5.onUnbind()
    6.onDestroy()

Service服务的生命周期还有一种情况:先调用starService()启动服务后,再调用bindService()进行绑定

  • 先调用startService()启动服务,后调用bindService()绑定服务的生命周期
    1.手动调用 starService() 方法
    2.onCreate()
    3.onStartCommand()
    4.服务运行中,手动调用 bindService() 方法
    5.onBind()
    6.绑定完成,服务运行中,手动调用 unbindService() 方法
    7.onUnbind()
    8.解除绑定完成,手动调用 stopService() 方法
    9.onDestroy()

生命周期中4个手动调用的方法

1.startService()
2.stopService()
3.bindService()
4.unbindService()

1.startService()
  • 作用:启动服务
  • 自动调用的方法:onCreate() 、onStartCommand()
  • 备注:onCreate()方法在生命周期中只调用一次,若 非首次调用 startService(),则跳过onCreate()方法直接调用onStartCommand()

onStartCommand()方法必须返回一个整数:描述在系统杀死服务后该如何继续运行
a. START_NOT_STICKY:不会重建服务,除非还存在未发送的intent,当服务不再是必须的,并且应用程序能够简单的重启那些未完成的工作时,这是避免服务运行的最安全的选项
b. START_STICKY:重建服务且调用onstartCommand(),但不会再次送入上一个intent,而是用一个null的intent来调用startCommand()。除非还有启动服务的intent未发送完,那么这些剩下的intent会继续发送
c. START_REDELIVER_INTENT:重建服务并用上一个已送过的intent调用onStartCommand() 。任何未发送完的intent也都会依次送入(适用于那些需要立即恢复工作的活跃服务,比如下载文件)

2.stopService()
  • 作用:停止服务
  • 自动调用的方法:onDestroy()

启动后绑定同个Service,若无解绑的前提下调用stopService()方法是无法停止服务的

3.bindService()
  • 作用:绑定服务
  • 自动调用的方法:onCreate() 、onBind()
4.unbindService()
  • 作用:解绑服务
  • 自动调用的方法:onUnbind() 、onDestroy()

Service的分类

类型

Service可按照运行地点、运行类型、功能进行分类

  • 运行地点:本地服务 、远程服务
  • 运行类型:前台服务、后台服务
  • 功能:可通信服务、不可通信服务
详细介绍

1.按 运行地点 分类

  • 本地服务
    • 特点:运行在主线进 、 主线程终止后,服务也会停止
    • 优点:节约资源 、 通信方便(由于在同一进程因此不需要IPC和AIDL进行通信)
    • 缺点:限制性大(主线程终止后,服务也停止)
    • 应用场景:需依附某个进程的服务
  • 远程服务
    • 特点:运行在独立进程 、 服务常驻后台,不受Activity影响
    • 优点:灵活(服务常驻在后台,不受其他Activity影响)
    • 缺点:消耗资源 、 通信复杂(AIDL或IPC)
    • 应用场景:系统级别服务

2.按 运行类型 分类

  • 前台服务

    • 特点:在通知栏显示通知(用户可看到)
    • 应用场景:服务使用时,需让用户知道并进行相关的操作(如:音乐播放服务)
  • 后台服务

    • 特点:处于后台的服务(用户无法看到)
    • 应用场景:服务使用时不需要让用户知道并进行相关的操作(如:天气的更新、日期同步)

3.按照 功能 分类

  • 不可通信服务
    • 特点:用startService()启动,调用者推出后Service仍然存在
    • 应用场景:服务不需与Activity或Service通信
  • 可通信服务
    • 通过调用bindService()启动

      • 特点:调用者退出后,随着调用者销毁
      • 应用场景:服务需与Activity通信,需控制服务开始时刻
      • 节约系统资源 = 第一次bindService()时才会创建服务的实例并运行:特别当服务 = Remote Service时,该效果越明显
      • 服务只是公开一个远程接口,供客户端远程调用执行方法
    • 通过调用startService() 、 bindService()启动

      • 特点:调用者退出后 ,随着调用者销毁
      • 应用场景:需与Activity通信,不需要控制服务开始时刻(服务一开始就运行)
使用讲解
  • 本地服务:这是最普通、最常用的后台服务

    • 使用步骤:
      1.新建子类继承Service类
      2.构建用于启动Service的Intent对象
      3.调用startService()启动Service,调用stopService()停止Service
      4.在清单配置文件 AndroidMainfest.xml里注册Service

      //注册Service服务
      <service android:name=".MyService"//Service的类名
      android:label="xxxx"///Service的名字,若不设置,默认Service类名
      android:icon="xxxxxx"//Service图标
      android:permission="xxxxxx"//申明此Service的权限,有提供了该权限的应用才能控制或连接此服务
      android:process="xxxxxx"//表示该服务时候在另一个进程中运行(远程服务)。默认本地服务,remote则设置远程服务
      android:enabled="true"//系统默认启动
      android:exported="xxxxx"//该服务时候能够被其他应用程序所控制或连接
      >
      </service>
      
  • 可通讯的Service
    • 上述本地Service只能单机使用,不能用于通信

    • 通过 bindService() 方法绑定的服务能达到通信功能

    • 步骤:
      1.新建子类MyService类继承Service类的类,并新建一个子类继承Binder类,写入与Acticity关联需要的方法,创建实例。

        public class MyService extends Service {
        
        private MyBinder mBinder = new MyBinder();
        
        //.....这里省略其他方法......
        
        //新建一个子类继承自Binder类
        class MyBinder extends Binder {
      
        public void service_connect_Activity() {
          System.out.println("Service关联了Activity,并在Activity执行了Service的方法");
      
          }
        }
      }
      

      2.构建启动Service的Intent对象,创建ServiceConnection的匿名类

      //创建ServiceConnection的匿名类
      private ServiceConnection connection = new ServiceConnection() {
      
      //重写onServiceConnected()方法和onServiceDisconnected()方法
      //在Activity与Service建立关联和解除关联的时候调用
        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
      
      //在Activity与Service解除关联的时候调用
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
          //实例化Service的内部类myBinder
          //通过向下转型得到了MyBinder的实例
          myBinder = (MyService.MyBinder) service;
          //在Activity调用Service类的方法
          myBinder.service_connect_Activity();
        }
      };
      
      
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
      
        Intent bindIntent = new Intent(this, MyService.class);
      
        //调用bindService()方法,以此启动服务
        bindService(bindIntent,connection,BIND_AUTO_CREATE);
        //参数说明
              //第一个参数:Intent对象
              //第二个参数:上面创建的Serviceconnection实例
              //第三个参数:标志位
              //这里传入BIND_AUTO_CREATE表示在Activity和Service建立关联后自动创建Service
              //这会使得MyService中的onCreate()方法得到执行,但onStartCommand()方法不会执行
      
      
      }
      
前台服务
  • 前台服务于后台服务最大的区别就在于:前台服务在下拉通知栏有显示通知,后台服务没有

  • 此外,前台服务的优先级比较高,不会因为系统内存不足而被回收

  • 使用:在原有的Service类对onCreate()方法进行稍微修改即可

      @Override
      public void onCreate() {
        super.onCreate();
        System.out.println("执行了onCreat()");
    
        //添加下列代码将后台Service变成前台Service
        //构建"点击通知后打开MainActivity"的Intent对象
        Intent notificationIntent = new Intent(this,MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,0);
    
        //新建Builer对象
        Notification.Builder builer = new Notification.Builder(this);
        builer.setContentTitle("前台服务通知的标题");//设置通知的标题
        builer.setContentText("前台服务通知的内容");//设置通知的内容
        builer.setSmallIcon(R.mipmap.ic_launcher);//设置通知的图标
        builer.setContentIntent(pendingIntent);//设置点击通知后的操作
    
        Notification notification = builer.getNotification();//将Builder对象转变成普通的notification
        startForeground(1, notification);//让Service变成前台Service,并在系统的状态栏显示出来
    
      }
    

    对于安卓8.0及以上的版本:调用 startForeground(1,notification) 方法可能会报错

Service与Thread的区别

相同点
  • Service与Thread的作用都是进行 异步操作
不同点
  • Service是运行在 进程主线程 上(依赖于进程),只要进程在,Service就可以继续运行。所有Activity都可以与Service关联,获得Binder实例后操作其中的方法。若要进行耗时操作需创建子线程
  • Thread是运行在 Activity 上的 工作线程 上(依赖于某一Activity),无法跨Activity操作子线程。当Activity销毁后,就无法获取到子线程的实例。

实际开发中一般会将Service与Thread相结合,即在Service中创建一个工作线程进行耗时操作。

多线程
  • 多线程的应用在开发中非常常见,主要有:
    1.继承Thread类
    2.实现Runnable接口
    3.AsyncTask
    4.Handler
    5.HandlerThread
    6.IntentService

感谢

文章出处:简书大神Carson_Ho
博客地址:https://www.jianshu.com/p/d963c55c3ab9

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269