startService启动流程---Service已经启动

2023-10-11 21:48

本文主要是介绍startService启动流程---Service已经启动,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在Service启动流程(startService)的最后,分析了在调用startService时可能存在的三种情况,本文分析第一种情况—Service已经启动。

Service启动流程(startService)中已经说明了Service已经启动时会执行函数sendServiceArgsLocked(r, false),接下来我们会分段分析这个函数。

private final void sendServiceArgsLocked(ServiceRecord r,boolean oomAdjusted) {final int N = r.pendingStarts.size();if (N == 0) {return;}  

理解这部分你的关键是r.pendingStarts,系统会将对Service的所有startService调用且还未执行保存在pendingStarts的ArrayList数据结构中,如果r.pendingStarts.size()==0,则表示对于Service来说,所有对于它的startService调用都已经执行完,则不需要继续执行后面的逻辑。

while (r.pendingStarts.size() > 0) {try {ServiceRecord.StartItem si = r.pendingStarts.remove(0);if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "+ r + " " + r.intent + " args=" + si.intent);if (si.intent == null && N > 1) {// If somehow we got a dummy null intent in the middle,// then skip it.  DO NOT skip a null intent when it is// the only one in the list -- this is to support the// onStartCommand(null) case.continue;}  

这部分还是需要好理解的,ServiceRecord.StartItem实例表示一次startService调用。首先从`r.pendingStarts中取出第一个,然后判断如果其intent是否为null,如果为null则表示此startService不必执行。

si.deliveredTime = SystemClock.uptimeMillis();
r.deliveredStarts.add(si);
si.deliveryCount++;
.....
int flags = 0;
if (si.deliveryCount > 1) {flags |= Service.START_FLAG_RETRY;
}
if (si.doneExecutingCount > 0) {flags |= Service.START_FLAG_REDELIVERY;
}
r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);  

这部分的代码我们看到了一个r.deliveredStarts结构,前面说过,r.pendingStarts保存的是还未真正执行的startService调用,r.deliveredStarts记录的是已经真正执行过的startService调用。接下来会有一个Binder的跨进程调用,直接进入ActivityThread即可看到scheduleServiceArgs函数。

public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,int flags ,Intent args) {ServiceArgsData s = new ServiceArgsData();s.token = token;s.taskRemoved = taskRemoved;s.startId = startId;s.flags = flags;s.args = args;queueOrSendMessage(H.SERVICE_ARGS, s);}  

如果看了我前面几篇Activity启动过程的话,这样的函数应该不陌生了,这个函数最终会调用一下逻辑:

private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {synchronized (this) {if (DEBUG_MESSAGES) Slog.v(TAG, "SCHEDULE " + what + " " + mH.codeToString(what)+ ": " + arg1 + " / " + obj);Message msg = Message.obtain();msg.what = what;msg.obj = obj;msg.arg1 = arg1;msg.arg2 = arg2;mH.sendMessage(msg);}
}  

我们就直接到mHhandleMessage函数

case SERVICE_ARGS:handleServiceArgs((ServiceArgsData)msg.obj);  

ok,接着往下,感觉马上就到重点了,哈哈

private void handleServiceArgs(ServiceArgsData data) {Service s = mServices.get(data.token);if (s != null) {try {if (data.args != null) {data.args.setExtrasClassLoader(s.getClassLoader());}int res;if (!data.taskRemoved) {res = s.onStartCommand(data.args, data.flags, data.startId);} else {s.onTaskRemoved(data.args);res = Service.START_TASK_REMOVED_COMPLETE;}QueuedWork.waitToFinish();try {ActivityManagerNative.getDefault().serviceDoneExecuting(data.token, 1, data.startId, res);} catch (RemoteException e) {// nothing to do.}ensureJitEnabled();} catch (Exception e) {if (!mInstrumentation.onException(s, e)) {throw new RuntimeException("Unable to start service " + s+ " with " + data.args + ": " + e.toString(), e);}}}
}

是不是看到onStartCommand的踪影了,是的,到这就执行完onStartCommand,这里还有一个非常重要的函数调用serviceDoneExecuting,我们都知道onStartCommand函数执行完后会返回一个标志,这个标志决定了Service的重启行为,但是系统究竟如何管理Service的重启行为呢,这个函数在后面会新开一篇分析。

这篇关于startService启动流程---Service已经启动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/191037

相关文章

SpringBoot启动报错的11个高频问题排查与解决终极指南

《SpringBoot启动报错的11个高频问题排查与解决终极指南》这篇文章主要为大家详细介绍了SpringBoot启动报错的11个高频问题的排查与解决,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一... 目录1. 依赖冲突:NoSuchMethodError 的终极解法2. Bean注入失败:No qu

一文带你了解SpringBoot中启动参数的各种用法

《一文带你了解SpringBoot中启动参数的各种用法》在使用SpringBoot开发应用时,我们通常需要根据不同的环境或特定需求调整启动参数,那么,SpringBoot提供了哪些方式来配置这些启动参... 目录一、启动参数的常见传递方式二、通过命令行参数传递启动参数三、使用 application.pro

SpringBoot项目启动报错"找不到或无法加载主类"的解决方法

《SpringBoot项目启动报错找不到或无法加载主类的解决方法》在使用IntelliJIDEA开发基于SpringBoot框架的Java程序时,可能会出现找不到或无法加载主类com.example.... 目录一、问题描述二、排查过程三、解决方案一、问题描述在使用 IntelliJ IDEA 开发基于

Spring AI ectorStore的使用流程

《SpringAIectorStore的使用流程》SpringAI中的VectorStore是一种用于存储和检索高维向量数据的数据库或存储解决方案,它在AI应用中发挥着至关重要的作用,本文给大家介... 目录一、VectorStore的基本概念二、VectorStore的核心接口三、VectorStore的

python之流程控制语句match-case详解

《python之流程控制语句match-case详解》:本文主要介绍python之流程控制语句match-case使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录match-case 语法详解与实战一、基础值匹配(类似 switch-case)二、数据结构解构匹

MyBatis-Plus中Service接口的lambdaUpdate用法及实例分析

《MyBatis-Plus中Service接口的lambdaUpdate用法及实例分析》本文将详细讲解MyBatis-Plus中的lambdaUpdate用法,并提供丰富的案例来帮助读者更好地理解和应... 目录深入探索MyBATis-Plus中Service接口的lambdaUpdate用法及示例案例背景

SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法

《SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法》本文主要介绍了SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法,具有一定的参考价值,感兴趣的可以了解一下... 目录方法1:更改IDE配置方法2:在Eclipse中清理项目方法3:使用Maven命令行在开发Sprin

在VSCode中本地运行DeepSeek的流程步骤

《在VSCode中本地运行DeepSeek的流程步骤》本文详细介绍了如何在本地VSCode中安装和配置Ollama和CodeGPT,以使用DeepSeek进行AI编码辅助,无需依赖云服务,需要的朋友可... 目录步骤 1:在 VSCode 中安装 Ollama 和 CodeGPT安装Ollama下载Olla

linux环境openssl、openssh升级流程

《linux环境openssl、openssh升级流程》该文章详细介绍了在Ubuntu22.04系统上升级OpenSSL和OpenSSH的方法,首先,升级OpenSSL的步骤包括下载最新版本、安装编译... 目录一.升级openssl1.官网下载最新版openssl2.安装编译环境3.下载后解压安装4.备份

C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)

《C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)》本文主要介绍了C#集成DeepSeek模型实现AI私有化的方法,包括搭建基础环境,如安装Ollama和下载DeepS... 目录前言搭建基础环境1、安装 Ollama2、下载 DeepSeek R1 模型客户端 ChatBo