美文网首页
Service整理

Service整理

作者: KyneMaster | 来源:发表于2019-12-26 11:21 被阅读0次

前言

Service相关知识和注意点的记录及整理。


目录

目录结构

1. 基础知识

  • 定义:服务,是Android四大组件之一, 属于 计算型组件
  • 作用:提供 需在后台长期运行的服务

    如:复杂计算、音乐播放、下载等

  • 特点:无用户界面、在后台运行、生命周期长

2. 生命周期

官方说明图
注意
  • 若一个Service被startService()多次启动,onCreate()也只会调用一次,只有onStartCommand()可以多次调用,其他只能调用一次。
  • bindService()启动的服务当所有客户端都解绑后,系统会销毁服务。
  • 异常情况下结束Service的生命周期不走OnDestory方法,比如系统清理,或者ANR结束

PS:
服务在被系统杀死后该如何继续运行

onStartCommand()返回一个整数

  • START_NOT_STICKY: 不会重建服务。除非还存在未发送的Intent,当服务不再是必需,并且应用程序能够简单地重启那些未完成的工作时,这是避免服务运行的最安全的选项。
  • START_STICKY: 重建服务 & 调用onStartCommand(),但不会再次送入上一个Intent,而是用null intent来调用onStartCommand(),除非还有启动服务的intent未发送完,那么这些剩下的Intent会继续发送(适用于媒体播放器类似服务,他们不执行命令,但需要一直运行并随时待命)
  • START_REDELIVER_INTENT: 重建服务 & 用上一个已送过的Intent调用onStartCommand()。任何未发送完的intent也都会依次送入。

3. 启动方式

讲到上述生命周期,便涉及到了两种启动方式:startService 和 bindService

3.1 第一种方式:通过startService启动Service

通过startService启动后,service会一直无限期运行下去,只有外部调用了stopService()或stopSelf()方法时,该Service才会停止运行并销毁。

3.2 第二种方式:通过bindService启动Service

  • bindService启动的服务和调用者之间是典型的client-server模式。调用者是client,service则是server端。service只有一个,但绑定到service上面的client可以有一个或很多个。这里所提到的client指的是组件,比如某个Activity。
  • client可以通过IBinder接口获取Service实例,从而实现在client端直接调用Service中的方法以实现灵活交互,这在通过startService方法启动中是无法实现的。
  • bindService启动服务的生命周期与其绑定的client息息相关。当client销毁时,client会自动与Service解除绑定。当然,client也可以明确调用Context的unbindService()方法与Service解除绑定。当没有任何client与Service绑定时,Service会自行销毁

4. Service基本使用

服务端继承Service,重写onCreate().onStartCommand().onBind().onDestroy().四个方法。清单文件manifest注册Service

4.1 StartService方式

Service端:

public class PushService extends Service{

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

Activity端:

//启动Service
Intent intent = new Intent(this, PushService.class);
startService(intent);

//停止Service
Intent intent = new Intent(this, PushService.class);
stopService(intent);

4.2 bindService方式

想要Service支持bindService调用:

  • 在Service的onBind()方法中返回IBinder类型的实例。
  • onBInd()方法返回的IBinder的实例需要能够返回Service实例本身

最简单的方法就是在service中创建binder的内部类,加入类似getService()的方法返回Service,这样绑定的client就可以通过getService()方法获得Service实例了。

Service端:

public class PushService extends Service{

    private static final String TAG = "PushService";

    //client 可以通过Binder获取Service实例
    public class MyBinder extends Binder {
        public PushService getService() {
            return PushService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_NOT_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //通过binder实现调用者client与Service之间的通信
        return new MyBinder();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    //getServiceName是Service暴露出去供client调用的公共方法
    public String getServiceName() {
        return TAG;
    }
}

Client端:
调用方式与start不同

  • 创建ServiceConnection类型实例,并重写onServiceConnected()方法和onServiceDisconnected()方法。
  • 当执行到onServiceConnected回调时,可通过IBinder实例得到Service实例对象,这样可实现client与Service的连接。
  • onServiceDisconnected回调被执行时,表示client与Service断开连接,在此可以写一些断开连接后需要做的处理。
//创建ServiceConnection类型实例
private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            
        }
    };

//启动绑定
Intent intent = new Intent(this, TestTwoService.class);
intent.putExtra("name", "ABCD");
bindService(intent, conn, BIND_AUTO_CREATE);

//解绑
unbindService(conn);

PS:
保证Service不被杀死?

  1. onStartCommand方式中,返回START_STICKY
  2. 提高Service的优先级
  3. 提升Service进程的优先级
  4. 在onDestroy方法里重启Service
  5. 系统广播监听Service状态
  6. 将APK安装到/system/app,变身为系统级应用

5. Activity和Service通信方式

使用方式自行查阅

5.1 bind启动开放公共方法。

5.2 回调接口的方式

5.3 通过广播(推荐)

5.4 观察者模式


6. Service和IntentService区别

6.1 区别

IntentService包含了Service所有特性。
不同:IntentService可以处理耗时操作。Service是依赖于主线程的,所以不能直接处理耗时操作。而IntentService会将任务依次插入到任务队列中,并逐个发送给onHandleIntent()来处理。省去了手动开线程的麻烦,并且自动停止Service

6.2 IntentService使用场景

很明显在需要按顺序,并且在后台处理请求时,优先IntentService。

6.3 源码分析

@Override
public void onCreate() {
    super.onCreate();
    // HandlerThread继承自Thread,内部封装了 Looper
    // 通过实例化andlerThread新建线程并启动
    // 所以使用IntentService时不需要额外新建线程
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    thread.start();

    // 获得工作线程的 Looper,并维护自己的工作队列
    mServiceLooper = thread.getLooper();

    //将上述获得Looper与新建的mServiceHandler进行绑定
    //新建的Handler是属于工作线程的。 ->> 分析1
    mServiceHandler = new ServiceHandler(mServiceLooper);
}

/**
 *  分析1 ServiceHandler绑定的是后台线程的Looper,而在Service停止时,Looper退出了,内存很快会被回收
 **/
private final class ServiceHandler extends Handler {
    public ServiceHandler(Looper looper) {
        super(looper);
    }

    // IntentService的handleMessage()把接收的消息交给onHandleIntent()处理
    @Override
    public void handleMessage(Message msg) {
        // onHandleIntent 方法在工作线程中执行,->> 分析2
        onHandleIntent((Intent)msg.obj);
        // 执行完调用 stopSelf() 结束服务。
        stopSelf(msg.arg1);
    }
}

/**
 *  分析2 
 *  onHandleIntent()是一个抽象方法,使用时需要重写的方法
 **/
@WorkerThread
protected abstract void onHandleIntent(Intent intent);

6.4 IntentService总结

  • 通过HandlerThread 单独开启1个工作线程:IntentService
  • 创建1个内部 Handler :ServiceHandler
  • 绑定 ServiceHandler 与 IntentService
  • 通过 onStartCommand() 传递服务intent 到ServiceHandler 、依次插入Intent到工作- 队列中 & 逐个发送给 onHandleIntent()
  • 通过onHandleIntent() 依次处理所有Intent对象所对应的任务

PS:

  1. 不适用bindService启动IntentService
  2. 在所有Intent被处理完后,系统自动关闭服务
  3. 复写onHandleIntent() & 在里面 根据Intent的不同进行不同线程操作
  4. IntentService优先级比普通线程高

结束

相关文章

  • Service整理

    概述 服务是脱离UI的一种运行程序,它负责了一些不必显示在屏幕上的运行过程。服务分为:本地服务和远程服务,此处只讨...

  • Service整理

    前言 Service相关知识和注意点的记录及整理。 目录 1. 基础知识 定义:服务,是Android四大组件之一...

  • Android音乐播放器的实现-Service 与 MediaP

    Android学习整理 - 系列 Android学习整理 - 6 -Service Android学习整理- 8 ...

  • Service通信整理

    客户端和服务端之间实现进程间通信 1.只有当你需要来自不同应用的客户端通过IPC通信来访问你的服务时,并且想在服务...

  • Android Service 适配 8.1+

    整理一下Android 8.0 以上版本 service 启动相关代码。在 Service 的 onCreate ...

  • Centos7-Systemd-Service自定义编写Serv

    Centos7-Systemd-Service自定义编写Service应用服务配置说明整理 From https:...

  • Service 知识梳理(1) - Service 问题整理

    一、Service 常见问题 由于Service比较简单,就不介绍基础的东西了,这篇文章主要是用于记录使用Serv...

  • Service Marketing 知识整理

    最近因为新冠的原因,除了宅在家里可以更聚焦自己的时间和精力以外,整个围绕“人”服务的市场也发生了很重要的变化。“在...

  • 获取mapper为null

    出现场景:通过反射获取service,然后service获取的mapper为null。解决方式: 原因分析:整理中...

  • Android面试题整理(二)

    Android面试题整理(二) 1.Service的相关知识 Service默认并不会运行在子线程中,它也不会运行...

网友评论

      本文标题:Service整理

      本文链接:https://www.haomeiwen.com/subject/urykoctx.html