四大组件-服务 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
    • 上述本地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

你可能感兴趣的:(四大组件-服务 Service)