Android学习总结之service篇

news2025/4/18 11:00:29

引言

在 Android 开发里,Service 与 IntentService 是非常关键的组件,它们能够让应用在后台开展长时间运行的操作。不过,很多开发者仅仅停留在使用这两个组件的层面,对其内部的源码实现了解甚少。本文将深入剖析 Service 和 IntentService 的源码,揭示它们的工作原理与区别。

Service 源码剖析

1. Service 概述

Service 是 Android 四大组件之一,用于在后台执行长时间运行的操作,且不提供用户界面。它可以通过 startService() 启动,也能通过 bindService() 绑定,从而与其他组件进行交互。

2. 生命周期方法

Service 的生命周期方法定义在 android.app.Service 类中,主要包含 onCreate()onStartCommand()onBind() 和 onDestroy()

Service
├─ onCreate()          // 初始化(仅一次)
├─ onStartCommand()    // 处理 startService 请求(可多次调用)
├─ onBind()            // 处理 bindService 请求(返回 IBinder)
├─ onDestroy()         // 释放资源
└─ 需手动管理子线程    // 耗时操作需自行创建线程
  • onCreate():服务创建时调用,通常用于初始化操作,此方法仅调用一次。
  • onStartCommand():每次调用 startService() 启动服务时都会调用该方法,其返回值决定了服务在被系统杀死后的重启策略。
  • onBind():当调用 bindService() 时调用,需要返回一个 IBinder 对象,用于与服务进行通信。
  • onDestroy():服务销毁时调用,可用于释放资源。

    A[Service 生命周期] --> B[onCreate()]
    B --> C{启动方式}
    C -->|startService()| D[onStartCommand()]
    C -->|bindService()| E[onBind()]
    D --> F[手动调用 stopSelf()/stopService()]
    E --> G[解绑时 onUnbind()]
    F & G --> H[onDestroy()]

    I[IntentService 生命周期] --> J[onCreate()]
    J --> K[创建 HandlerThread & ServiceHandler]
    K --> L[onStartCommand() 调用 onStart()]
    L --> M[ServiceHandler 处理 Message]
    M --> N[调用 onHandleIntent(intent)(子线程)]
    N --> O[自动调用 stopSelf()]
    O --> P[onDestroy()(Looper.quit())]

3. 启动流程

当调用 startService() 方法时,最终会调用到 ActivityManagerService 中的相关方法,它会负责创建 Service 实例并调用其生命周期方法。

// ActivityManagerService.java
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, int userId) {
    // 处理启动服务的逻辑
    synchronized(this) {
        // ...
        ServiceRecord r = startServiceLocked(caller, service, resolvedType, callingPid,
                callingUid, userId);
        // ...
    }
    // ...
}

4. 注意事项

Service 默认在主线程中运行,若在 Service 中执行耗时操作,会导致界面卡顿。因此,若有耗时操作,应在 Service 中手动创建子线程。

IntentService 源码剖析

1. IntentService 概述

IntentService 是 Service 的子类,它是一个异步的、会自动停止的服务。它内部使用 HandlerThread 创建了一个子线程,所有的 Intent 都会在这个子线程中处理。

2. 关键源码分析

IntentService(继承 Service)
├─ onCreate()          
│  └─ 创建 HandlerThread(子线程)
│  └─ 获取 Looper,创建 ServiceHandler(绑定子线程 Looper)
├─ onStartCommand()    
│  └─ 调用 onStart(),将 Intent 封装为 Message 发送给 ServiceHandler
├─ ServiceHandler(Handler 子类)
│  └─ handleMessage():调用 onHandleIntent() 处理 Intent,调用 stopSelf()
├─ onHandleIntent()     // 开发者需实现的核心业务逻辑(在子线程执行)
└─ onDestroy()         
   └─ 调用 Looper.quit() 终止子线程
// android.app.IntentService
public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

    public IntentService(String name) {
        super();
        mName = name;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

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

    protected abstract void onHandleIntent(@Nullable Intent intent);
}

3. 关键流程

  • onCreate():创建一个 HandlerThread 并启动它,然后获取该线程的 Looper,创建一个 ServiceHandler 并关联该 Looper
  • onStartCommand():调用 onStart() 方法,将传递的 Intent 封装成 Message 发送给 ServiceHandler
  • ServiceHandler 的 handleMessage():调用 onHandleIntent() 方法处理 Intent,处理完成后调用 stopSelf() 停止服务。

4. 特点总结

  • 异步处理:所有的 Intent 都会在子线程中处理,避免了在主线程中执行耗时操作。
  • 自动停止:当所有的 Intent 处理完成后,IntentService 会自动调用 stopSelf() 方法停止服务。
  • 顺序处理IntentService 会按照 Intent 到达的顺序依次处理,不会并发处理多个 Intent

Service 与 IntentService 的区别

1. 线程方面

  • Service 默认在主线程中运行,若要执行耗时操作,需手动创建子线程。
  • IntentService 内部创建了一个子线程,所有的 Intent 都会在该子线程中处理。

2. 停止方式

  • Service 需要手动调用 stopSelf() 或 stopService() 来停止服务。
  • IntentService 在处理完所有的 Intent 后会自动停止。

3. 处理方式

  • Service 可以同时处理多个请求。
  • IntentService 会按顺序依次处理 Intent,不会并发处理。

总结图表

特性ServiceIntentService
继承关系直接继承 ContextWrapper,实现 ComponentCallbacks2继承自 Service,是 Service 的子类
线程环境默认运行在主线程(UI 线程),需手动创建子线程处理耗时任务内部创建 HandlerThread 子线程,通过 ServiceHandler 在子线程处理所有 Intent
启动后的处理逻辑需重写 onStartCommand,手动处理业务逻辑,需手动调用 stopSelf() 停止服务自动将 Intent 封装为 Message,通过 ServiceHandler 按顺序处理,处理完自动停止
生命周期控制需手动调用 stopService() 或 stopSelf() 停止,或通过 onStartCommand 返回值控制重启策略无需手动停止,处理完所有 Intent 后自动调用 stopSelf() 停止
并发处理可同时处理多个 startService 请求(需自行处理多线程同步)按 Intent 接收顺序串行处理,同一时间仅处理一个 Intent
默认 onBind 返回值返回 null(需开发者自定义 IBinder直接返回 null(不支持绑定,如需绑定需自定义子类)
适用场景复杂后台逻辑(如跨组件通信、长期运行任务)简单异步任务(如网络请求、文件操作),任务完成后自动停止

结论

        若需要执行简单的异步任务且任务完成后自动停止服务,可选择 IntentService;若需要与其他组件进行交互或同时处理多个请求,则可选择 Service

感谢观看!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2330016.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring mvc异步请求 sse 大文件下载 断点续传下载Range

学习连接 异步Servlet3.0 Spring Boot 处理异步请求(DeferredResult 基础案例、DeferredResult 超时案例、DeferredResult 扩展案例、DeferredResult 方法汇总) spring.io mvc Asynchronous Requests 官网文档 spring.io webflux&webclient官网文…

Opencv计算机视觉编程攻略-第十节 估算图像之间的投影关系

目录 1. 计算图像对的基础矩阵 2. 用RANSAC 算法匹配图像 3. 计算两幅图像之间的单应矩阵 4. 检测图像中的平面目标 图像通常是由数码相机拍摄的,它通过透镜投射光线成像,是三维场景在二维平面上的投影,这表明场景和它的图像之间以及同一…

14.流程自动化工具:n8n和家庭自动化工具:node-red

n8n 安装 docker方式 https://docs.n8n.io/hosting/installation/docker/ #https://hub.docker.com/r/n8nio/n8n docker pull n8nio/n8n:latest docker rm -f n8n; docker run -it \ --network macvlan --hostname n8n \ -e TZ"Asia/Shanghai" \ -e GENERIC_TIME…

图形渲染: tinyrenderer 实现笔记(Lesson 1 - 4)

目录 项目介绍环境搭建Lesson 1: Bresenham’s Line Drawing Algorithm(画线算法)Lesson 2: Triangle rasterization 三角形光栅化Scanline rendering 线性扫描Modern rasterization approach 现代栅格化方法back-face culling 背面剔除 Lesson 3: Hidde…

大规模硬件仿真系统的编译挑战

引言: 随着集成电路设计复杂度的不断提升,硬件仿真系统在现代芯片设计流程中扮演着越来越重要的角色。基于FPGA(现场可编程门阵列)的商用硬件仿真系统因其灵活性、全自动化、高性能和可重构性,成为验证大规模集成电路设…

记一次常规的网络安全渗透测试

目录: 前言 互联网突破 第一层内网 第二层内网 总结 前言 上个月根据领导安排,需要到本市一家电视台进行网络安全评估测试。通过对内外网进行渗透测试,网络和安全设备的使用和部署情况,以及网络安全规章流程出具安全评估报告。本…

【8】搭建k8s集群系列(二进制部署)之安装work-node节点组件(kubelet)

一、下载k8s二进制文件 下载地址: https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG -1.20.md 注:打开链接你会发现里面有很多包,下载一个 server 包就够了,包含了 Master 和 Worker Node 二进制文件。…

使用 VIM 编辑器对文件进行编辑

一、VIM 的两种状态 VIM(vimsual)是 Linux/UNIX 系列 OS 中通用的全屏编辑器。vim 分为两种状态,即命令状态和编辑状态,在命令状态下,所键入的字符系统均作命令来处理;而编辑状态则是用来编辑文本资料&…

visual studio 2022的windows驱动开发

在visual studio2022中&#xff0c;若在单个组件中找不到Windows Driver Kit (WDK)选项&#xff0c;可通过提升vs版本解决&#xff0c;在首次选择时选择WDM 创建好项目在Source Files文件夹中创建一个test.c文件&#xff0c;并输入以下测试代码&#xff1a; #include <ntdd…

基于大数据的美团外卖数据可视化分析系统

【大数据】基于大数据的美团外卖数据可视化分析系统 &#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统通过对海量外卖数据的深度挖掘与分析&#xff0c;能够为美团外卖平台提供运营决策支…

vue2打包部署到nginx,解决路由history模式下页面空白问题

项目使用的是vue2&#xff0c;脚手架vue-cli 4。 需求&#xff1a;之前项目路由使用的是hash&#xff0c;现在要求调整为history模式&#xff0c;但是整个过程非常坎坷&#xff0c;遇到了页面空白问题。现在就具体讲一下这个问题。 首先&#xff0c;直接讲路由模式由hash改为…

【数据结构】排序算法(中篇)·处理大数据的精妙

前引&#xff1a;在进入本篇文章之前&#xff0c;我们经常在使用某个应用时&#xff0c;会出现【商品名称、最受欢迎、购买量】等等这些榜单&#xff0c;这里面就运用了我们的排序算法&#xff0c;作为刚学习数据结构的初学者&#xff0c;小编为各位完善了以下几种排序算法&…

AI随身翻译设备:从翻译工具到智能生活伴侣

文章目录 AI随身翻译设备的核心功能1. 实时翻译2. 翻译策略3. 翻译流程4. 输出格式 二、AI随身翻译设备的扩展功能1. 语言学习助手2. 旅行助手3. 商务助手4. 教育助手5. 健康助手6. 社交助手7. 技术助手8. 生活助手9. 娱乐助手10. 应急助手 三、总结四、未来发展趋势&#xff0…

chromadb 安装和使用

简介 Chromadb 是一个开源的嵌入式向量数据库&#xff0c;专为现代人工智能和机器学习应用设计&#xff0c;旨在高效存储、检索和管理向量数据。以下是关于它的详细介绍&#xff1a; 核心特性 易于使用&#xff1a;提供了简洁直观的 API&#xff0c;即使是新手也能快速上手…

LabVIEW 在故障诊断中的算法

在故障诊断领域&#xff0c;LabVIEW 凭借其强大的图形化编程能力、丰富多样的工具包以及卓越的功能性能&#xff0c;成为工程师们进行故障诊断系统开发的得力助手。通过运用各种算法&#xff0c;能够对采集到的信号进行全面、深入的分析处理&#xff0c;从而准确地诊断出系统中…

springboot 启动方式 装配流程 自定义starter 文件加载顺序 常见设计模式

目录 springboot介绍 核心特性 快速搭建 Spring Boot 项目 方式一&#xff1a;使用 Spring Initializr 方式二&#xff1a;使用 IDE 插件 示例代码 1. 创建项目并添加依赖 2. 创建主应用类 3. 创建控制器类 4. 运行应用程序 配置文件 部署和监控 部署 监控 与其…

Android学习之Material Components

以下是 Material Design 提供的核心控件列表&#xff08;基于最新 Material Components for Android 库&#xff09;&#xff0c;按功能分类整理&#xff1a; 1. 基础按钮类 控件名称类名说明MaterialButtoncom.google.android.material.button.MaterialButton遵循 Material 规…

sentinel新手入门安装和限流,热点的使用

1 sentinel入门 1.1下载sentinel控制台 &#x1f517;sentinel管理后台官方下载地址 下载完毕以后就会得到一个jar包 1.2启动sentinel 将jar包放到任意非中文目录&#xff0c;执行命令&#xff1a; java -jar 名字.jar如果要修改Sentinel的默认端口、账户、密码&#xff…

Ubuntu 22 Linux上部署DeepSeek R1保姆式操作详解(Xinference方式)

一、安装步骤 1.基础环境安装 安装显卡驱动、cuda&#xff0c;根据自己硬件情况查找相应编号&#xff0c;本篇不介绍这部分内容&#xff0c;只给出参考指令&#xff0c;详情请读者自行查阅互联网其它参考资料。 sudo apt install nvidia-utils-565-server sudo apt install…

CTF类题目复现总结-hashcat 1

一、题目地址 https://buuoj.cn/challenges#hashcat二、复现步骤 1、下载附件&#xff0c;解压得到What kind of document is this_文件&#xff1b; 2、用010 Editor打开What kind of document is this_文件&#xff0c;发现是office文件&#xff1b; 3、将后缀名改为ppt时…