AMS概念以及面试相关整理
1、ActivityManagerService是什么?什么时候初始化的?有什么作用?
ActivityManagerService(AMS)是什么?
ActivityManagerService(简称AMS)是Android操作系统中的一个核心服务,主要负责管理和监控系统中所有Activity的生命周期,以及协调四大组件(Activity、Service、Broadcast Receiver和Content Provider)的启动、切换和调度。AMS还负责应用进程的管理和调度,确保系统资源的有效利用和分配。
何时初始化ActivityManagerService?
AMS的初始化发生在Android系统启动过程中,具体来说,是在SystemServer进程开启时进行的。在SystemServer进程中,会通过SystemServiceManager来启动AMS服务,这通常发生在SystemServer类的startBootstrapServices()
方法中。AMS服务的启动是通过反射机制创建AMSEx对象,然后通过startService()
方法启动服务.
ActivityManagerService的作用是什么?
AMS的主要作用包括:
-
管理Activity的生命周期,包括创建、启动、暂停、恢复和销毁Activity。
-
协调四大组件的启动和切换,确保它们按照预期的顺序和行为运行。
-
管理应用进程,包括进程的创建、调度和终止。
-
维护系统的全局状态,如当前正在前台运行的Activity、最近任务列表等。
-
提供API供其他系统服务和应用程序查询和控制Activity和进程的状态。
AMS作为系统的关键部分,对于保证Android系统的稳定性和性能至关重要。
2、ActivityThread是什么?ApplicationThread是什么?他们的区别是什么?
ActivityThread
ActivityThread是Android操作系统中的一个核心类,它代表了Android应用程序的主线程,也就是UI线程。ActivityThread是Android应用程序启动的入口点,它负责管理应用程序的生命周期,包括启动Activity、处理Intent、管理服务和广播接收器等。ActivityThread通过Handler机制来处理消息循环,从而响应各种系统事件和用户输入。
ApplicationThread
ApplicationThread是ActivityThread的内部类,它是一个Binder对象,主要用于ActivityThread与ActivityManagerService(AMS)之间的通信。ApplicationThread作为客户端Binder,允许AMS服务调用应用程序进程中的方法,比如启动Activity或者服务。
区别
ActivityThread和ApplicationThread的主要区别在于它们的角色和用途。ActivityThread是应用程序的主线程,负责处理应用程序的生命周期和UI更新,而ApplicationThread则是ActivityThread与AMS之间的通信桥梁,用于处理与系统服务相关的操作。简单来说,ActivityThread是面向应用程序的,而ApplicationThread是面向系统服务的。
在Android系统启动时,ActivityThread会被创建并启动,它会通过attach方法与AMS建立连接,这时会创建ApplicationThread实例,以便于后续与AMS的通信。因此,ApplicationThread是ActivityThread在与AMS交互时使用的工具,而ActivityThread本身则是处理应用程序逻辑的主体。
3、 Instrumentation是什么?和ActivityThread是什么关系?
Instrumentation
Instrumentation在Android中是一个特殊的类,它可以被认为是应用进程的管家。每个Android应用程序只有一个Instrumentation对象,这个对象在应用程序的生命周期中扮演着重要的角色。Instrumentation对象的主要职责是监听和介入应用程序的生命周期事件,例如Activity的创建、销毁和系统的启动等。它还提供了一系列的方法,允许开发者在特定的生命周期事件发生时执行自定义的代码,这对于测试和调试应用程序特别有用。
ActivityThread与Instrumentation的关系
ActivityThread是Android应用程序的主线程,负责管理应用程序的生命周期和UI更新。每个Activity都持有Instrumentation对象的一个引用,这样ActivityThread在执行创建或暂停某个Activity的操作时,都需要通过Instrumentation来进行具体的操作,即回调Activity的生命周期方法。Instrumentation对象的存在使得ActivityThread能够在执行生命周期方法之前或之后插入额外的逻辑,这对于扩展和定制Android应用程序的行为非常重要2.
总结来说,Instrumentation是一个用于介入和监听Android应用程序生命周期事件的工具,而ActivityThread是负责执行这些生命周期事件的主线程。两者紧密协作,共同确保Android应用程序能够正确地启动、运行和关闭。
4、ActivityManagerService和zygote进程通信是如何实现的?
应 用启动时,Launcher进程请求AMS。 AMS发送创建应用进程请求 ,Zygote进程接受请求并fork应用进程 客户端发送请求调 用 Process.start() 方法新建进程连 接 调 用 的 是 ZygoteState.connect() 方 法 , ZygoteState 是 ZygoteProcess 的 内 部 类 。ZygoteState里 用 的 LocalSocket
public static ZygoteState connect( LocalSocketAddress address) throws IOException { DataInputStream zygoteInputStream = null ; BufferedWriter zygoteWriter = null; final LocalSocket zygoteSocket = new LocalSocket( ) ; try { zygoteSocket . connect(address); zygoteInputStream = new DataInputStream( zygoteSocket .getInputStream()) ; zygoteWriter = new BufferedWriter( new OutputStreamWriter( zygoteSocket .getOutputStream()) , 256) ; } catch (IOException ex) { try { zygoteSocket .close() ; } catch (IOException ignore) { }throw ex ; }return new ZygoteState(zygoteSocket , zygoteInputStream , zygoteWriter , Arrays .asList(abiListString .split(","))) ; }
Zygote 处理客户端请求 Zygote 服 务 端 接 收 到 参 数 之 后 调 用 ZygoteConnection.processOneCommand() 处 理 参 数 ,并fork 进 程 最 后 通过 fifindStaticMain() 找到 ActivityThread 类的 main() 方法并执行 ,子进程就启动了
5、ActivityManager、ActivityManagerService、ActivityManagerNative、ActivityManagerproxy的关系
### ActivityManager、ActivityManagerService、ActivityManagerNative、ActivityManagerProxy的关系
在Android操作系统中,ActivityManager、ActivityManagerService、ActivityManagerNative和ActivityManagerProxy是与活动管理器相关的几个关键组件,它们协同工作以管理和监控应用程序的生命周期和系统资源。
1. **ActivityManager**:这是一个Android系统中的接口,定义了一系列方法,用于管理应用程序的活动(Activities)和其他相关的系统级功能。
2. **ActivityManagerService**:这是一个后台服务,负责实现ActivityManager接口中定义的方法。它是Android系统中管理活动和应用程序生命周期的核心服务。ActivityManagerService运行在系统的服务进程中,通常是system_server进程。
3. **ActivityManagerNative**:这是一个Binder接口,它是ActivityManagerService的客户端侧代理。ActivityManagerNative本身并不实现任何方法,而是作为一个Binder通信类存在,它的作用是将客户端的请求转发给ActivityManagerService。
4. **ActivityManagerProxy**:这是ActivityManagerNative的一个实现类,它实际上是一个Binder代理类,用于在客户端和ActivityManagerService之间进行Binder通信。当客户端调用ActivityManager的方法时,这些调用会被封装在ActivityManagerProxy中,并通过Binder机制传递给ActivityManagerService。
在客户端代码中,通常不会直接与ActivityManagerService交互,而是通过ActivityManagerNative和ActivityManagerProxy来间接调用ActivityManagerService提供的服务。这样的设计允许客户端代码透明地与ActivityManagerService通信,同时也支持跨进程通信,因为ActivityManagerService可能运行在不同的进程中。
总结来说,ActivityManager是一个接口,ActivityManagerService是实现该接口的服务,ActivityManagerNative是客户端与服务端通信的Binder接口,而ActivityManagerProxy是ActivityManagerNative的具体实现,它作为Binder代理在客户端和ActivityManagerService之间进行通信.
6、如何使用Instrumentation来优化Android应用的性能
Instrumentation在Android中不仅用于测试,还可以用来优化应用性能。以下是一些使用Instrumentation来优化Android应用性能的方法:
-
生命周期耗时监测:通过Hook Instrumentation实现生命周期耗时监测。这涉及到反射获取ActivityThread的实例,然后替换其内部的Instrumentation对象为自定义的Instrumentation,这样就可以在Activity的生命周期方法前后插入自定义的日志或分析代码,从而监测生命周期的耗时情况[1]。
-
性能分析工具:Instrumentation提供了性能分析工具,可以帮助开发人员记录应用程序的响应时间、CPU和内存使用情况等指标。这些工具可以帮助开发人员识别应用程序中的性能瓶颈,以便进行针对性的优化[2]。
-
应用启动时间优化:通过Instrumentation可以监控应用的启动时间,包括冷启动、温启动和热启动的时间。根据监控数据,开发人员可以采取措施减少启动时间,例如优化资源加载、减少初始化代码量等[3]。
-
测试驱动开发:利用Instrumentation编写自动化测试,确保应用程序的各个组件在各种情况下都能正确运行。这种测试驱动的方式有助于提前发现潜在的性能问题,并确保在后续的开发中不会引入新的性能问题[2]。
-
内存泄漏检测:Instrumentation可以配合内存分析工具(如LeakCanary)来检测应用中的内存泄漏。通过Instrumentation触发GC(垃圾回收)并检查是否有未释放的对象,可以帮助开发人员及时发现和解决内存泄漏问题。
-
CPU使用率监控:使用Instrumentation监控CPU的使用情况,分析哪些操作或函数导致CPU负载过高,进而进行优化。
-
网络请求分析:Instrumentation可以帮助监控网络请求的次数、大小和延迟,从而优化网络使用效率,减少不必要的请求或优化请求的内容。
通过上述方法,Instrumentation成为了Android应用性能优化的有力工具。开发人员可以结合具体的应用场景和性能瓶颈,灵活运用Instrumentation提供的功能,来提升应用的性能和用户体验。
7、如果我想做一个全面的Android应用性能优化,应该怎样开始?
开始全面的Android应用性能优化
要进行全面的Android应用性能优化,您可以按照以下步骤进行:
-
性能分析:首先,使用性能分析工具(如LeakCanary、MAT、StrictMode等)来识别内存泄漏、CPU使用率高的代码段、网络请求的瓶颈以及其他可能的性能问题。
-
内存优化:优化内存使用,包括减少内存泄漏、优化Bitmap的使用、避免内存抖动,以及优化数据结构和算法以减少内存消耗。
-
布局优化:减少布局层级,优化布局结构,使用ConstraintLayout替代嵌套的LinearLayout和RelativeLayout,使用merge标签和ViewStub来延迟加载布局[2]。
-
异步处理:避免在UI线程进行耗时操作,使用AsyncTask、HandlerThread或其他并发机制将耗时操作移至后台线程执行,以避免界面卡顿。
-
网络优化:减少网络请求的次数和大小,使用缓存策略(如OkHttp的缓存机制)来减少不必要的网络流量,优化网络请求的优先级和顺序。
-
启动优化:优化应用启动时间,包括减少启动时的工作量、优化冷启动流程、预加载必要的资源和服务。
-
电量优化:优化应用的电量使用,例如限制后台活动、优化网络策略、合理使用GPS和传感器等。
-
测试和验证:在不同的设备和操作系统版本上测试优化后的应用,确保性能提升同时保持兼容性和稳定性。
-
持续监控:即使在发布后,也应持续监控应用的性能,使用实时分析工具(如Firebase Performance Monitoring)来跟踪关键性能指标,并快速响应任何新出现的问题。
-
反馈循环:收集用户反馈,特别是关于性能的反馈,并将其纳入未来的优化工作中。
以上步骤结合了最新的性能优化技术和最佳实践,可以帮助您全面提升Android应用的性能
Android应用启动流程概述
Android应用的启动流程是一个相对复杂的过程,它涉及到多个系统组件和进程的协作。以下是Android应用启动的基本步骤:
-
用户交互:用户在设备的主屏幕点击应用图标,触发启动请求。
-
启动器(Launcher):启动器接收到用户的点击事件后,向系统的ActivityManagerService(AMS)发送一个Intent,请求启动指定的应用。
-
AMS处理:AMS是Android系统中负责管理Activity的服务,它接收到来自启动器的启动请求后,会检查目标Activity是否已经存在于正在运行的进程中。如果不存在,AMS会向Zygote进程发送一个请求,要求它fork出一个新的进程来承载这个Activity。
-
Zygote进程:Zygote是Android系统中的一个特殊进程,它被设计为一个共享进程,用于快速启动新的应用进程。当Zygote进程接收到来自AMS的fork请求时,它会复制自己的内存空间和文件描述符,创建一个全新的进程,这个新进程称为应用进程。
-
ActivityThread:在新创建的应用进程中,Zygote进程会启动ActivityThread,这是一个Java进程的入口点,它负责管理应用的生命周期和消息循环。ActivityThread会加载应用的Dex字节码,并准备好应用环境。
-
Activity的创建:ActivityThread会调用Looper.loop()来启动消息循环,并在消息循环中处理各种事件,包括创建Activity。ActivityThread会调用Activity的onCreate()、onStart()和onResume()方法,最终使得Activity显示在屏幕上。
启动流程的优化
为了优化Android应用的启动性能,可以考虑以下几个方面:
-
减少启动时的工作量:避免在启动时进行不必要的计算和资源加载,比如延迟加载非关键资源和功能。
-
优化布局:简化布局层次结构,使用ConstraintLayout等高效布局,减少布局的重绘和测量开销。
-
预热资源:在应用启动前预先加载一些资源,比如在后台线程中预加载图像和字体,以减少启动时的等待时间。
-
使用启动屏:在应用启动时显示一个简单的启动屏,让用户知道应用正在加载,同时也可以隐藏启动过程中的闪烁和延迟。
-
避免立即执行耗时操作:在Activity的onCreate()方法中避免立即执行耗时的操作,可以将这些操作放到后台线程中去执行。
-
使用ProGuard或R8进行代码混淆和压缩:这可以减少APK的体积,加快安装和启动速度。
-
使用动态特性模块:通过动态特性模块(Dynamic Feature Module)来按需加载应用的某些部分,从而减少初次启动时的加载时间。
以上步骤和建议结合了最新的性能优化技术和最佳实践,可以帮助您全面提升Android应用的性能。
相关文章:
AMS概念以及面试相关整理
1、ActivityManagerService是什么?什么时候初始化的?有什么作用? ActivityManagerService(AMS)是什么? ActivityManagerService(简称AMS)是Android操作系统中的一个核心服务&#…...
Vmware下减小Ubuntu系统占用系统盘大小
1、虚拟机设置下占用空间 如图,给虚拟机分配了120GB,已经占用116.9GB,开机会提示空间不足。 2、实际使用空间 ubuntu系统下使用“df -h”命令查看实际使用空间大小50GB左右 造成这个原因是,虚拟机的bug:在虚拟机的ub…...
面试题-Elasticsearch集群架构和调优手段(超全面)
对于Elasticsearch(ES),我了解并有经验。在我之前的公司,我们有一个相对大型的ES集群,以下是该集群的架构和一些调优手段的概述: 1. 集群架构 集群规模:我们的ES集群由15个节点组成,…...
python基础练习题6
1、找出10000以内能被5或6整除,但不能被两者同时整除的数(函数) def find_numbers(m,n):result []for num in range(m,n):if (num % 5 0 or num % 6 0) and not (num % 5 0 and num % 6 0):result.append(num)return resultprint(find_…...
Chrome 插件各模块使用 Fetch 进行接口请求
Chrome 插件各模块使用 Fetch 进行接口请求 常规网页可以使用 fetch() 或 XMLHttpRequest API 从远程服务器发送和接收数据,但受到同源政策的限制。 内容脚本会代表已注入内容脚本的网页源发起请求,因此内容脚本也受同源政策的约束,插件的来…...
内存可见性
内存可见性 一:内存可见性1.2: 二:解决内存可见性问题2.1 volatile关键字2.2:synchronized关键字解决内存可见性问题 一:内存可见性 public class Demo1 {public static int count 0;public static void main(String[] args) throws InterruptedException {Thread t1new Thre…...
Android room 在dao中不能使用挂起suspend 否则会报错
错误: Type of the parameter must be a class annotated with Entity or a collection/array of it. kotlin.coroutines.Continuation<? super kotlin.Unit> $completion); 首先大家检查一下几个点 一、kotlin-kapt 二、 是否引入了 room-ktx 我是2024年…...
【stable diffusion扩散模型】一篇文章讲透
目录 一、引言 二、Stable Diffusion的基本原理 1 扩散模型 2 Stable Diffusion模型架构 3 训练过程与算法细节 三、Stable Diffusion的应用领域 1 图像生成与艺术创作 2 图像补全与修复 3 其他领域 四、Stable Diffusion的优势与挑战 👉优势 …...
数据链路层之信道:数字通信的桥梁与守护者
✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…...
SQL109 纠错4(组合查询,order by..)
SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_state MI UNION SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_state IL ORDER BY cust_name;order by子句,必须位于最后一条select语句之后...
Spring Boot + Vue 实现文件导入导出功能
文章目录 1、概述2、后端实现(Spring Boot)3、前端实现(Vue)4、总结 1、概述 在现代Web应用开发中,文件的导入导出是一个常见的需求。Spring Boot作为后端开发的强大框架,搭配前端框架Vue,可…...
vue watch 深度监听
vue2文档:API — Vue.js vue3文档:侦听器 | Vue.js watch 可以用来监听页面中的数据,但如果监听的源是对象或数组,则使用深度监听,强制深度遍历源,以便在深度变更时触发回调。 一,监听 <t…...
Qt源码调试步骤记录
1.源码: 两种方式,要么安装qt时选择source,要么从官网下载源码,然后在qt creator中设置路径。二选一即可。我选的第二种。 1.1.第一种,安装时选择source: 1.2.第二种,下载源码设置路径&#x…...
大数据面试英文自我介绍参考(万字长文)
发现有一个怪圈,如果码农年龄35+,除非非常匹配,不然在国内企业筛选可能就筛选不过。国外码农可以干到40+、50+。一些外企,对年龄35+的码农依然青睐。这些外企对英文是有要求,通常是要英文自我介绍,下面提供一些英文自我介绍参考。 参考1: Good morning/afternoon, I a…...
外包干了5天,技术退步明显.......
先说一下自己的情况,大专生,18年通过校招进入杭州某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能测…...
Docket常见的软件部署1
1 安装MySQL # 查看MySQL镜像 docker search mysql # 拉起镜像 docker pull mysql:5.7 # 创建MySQL数据映射卷,防止数据不丢失 mkdir -p /hmoe/tem/docker/mysql/data/ # 启动镜像 docker run -d --name mysql -e MYSQL_ROOT_PASSWORD123456 -p 3306:3306 -v /home…...
Qt源程序编译及错误问题解决
Error 5 while parsing C:/qt-everywhere-src-6.6.2/qt-build/qtdeclarative/src/qmlmodels/meta_types/qt6qmlmodels_release_metatypes.json: illegal value .json 文件为空文件0字节,加 “[]”,不要引号。可以解决这类错误。 Qt编译 Qt for Windows…...
作业练习(python)
第一题: cel eval(input()) fah 9 / 5 * cel 32 print("%.1f" % fah) 第二题: radius, length eval(input()) area radius * radius * 3.14159267 volume area * length print("%.2f" % area) print("%.2f" …...
Wireshark使用相关
1.wireshark如何查看RST包 tcp.flags.reset1 RST表示复位,用来异常的关闭连接,在TCP的设计中它是不可或缺的。发送RST包关闭连接时,不必等缓冲区的包都发出去(不像上面的FIN包),直接就丢弃缓存区的包发送R…...
相机标定学习记录
相机标定是计算机视觉和机器视觉领域中的一项基本技术,它的主要目的是通过获取相机的内部参数(内参)和外部参数(外参),以及镜头畸变参数,建立起现实世界中的点与相机成像平面上对应像素点之间准…...
CSS 滚动条样式修改
1、滚动条整体部分 使用 ::-webkit-scrollbar 注意:这个必须要加,不然修改的样式不生效 ::-webkit-scrollbar {width: 10px;//修改滚动条宽度 }2、滚动条中的滑块 使用 ::-webkit-scrollbar-thumb ::-webkit-scrollbar-thumb {border-radius: 8px;b…...
谈谈配置中心?
配置中心可以做集中式的服务配置管理,比如配置一些数据库连接的URL,一些共用的配置且可动态调整的参数。如果不采用集中式的管理,会导致修改起来特别麻烦,一个个的修改特别繁琐。 Nacos Config配置中心中采用的是客户端拉取数据&a…...
人工智能(pytorch)搭建模型25-基于pytorch搭建FPN特征金字塔网络的应用场景,模型结构介绍
大家好,我是微学AI,今天给大家介绍一下人工智能(pytorch)搭建模型25-基于pytorch搭建FPN特征金字塔网络的应用场景,模型结构介绍。特征金字塔网络(FPN)是一种深度学习模型结构,主要应用于目标检测任务中&am…...
JRT业务开发起步
这是一段充满挑战与奋斗的旅程,自第一行Java代码的写下起,便历经重重险阻。从细微的代码行,逐步汇聚成实用的工具类方法;从工具类方法的积累,逐渐构建起功能强大的工具包;再从工具包的整合,最终…...
深度解析:国内主流音视频产品的核心功能与市场表现
前言 当前音视频开发领域呈现出多样化竞争态势,其中声网(Agora)、即构(ZEGO)等云通讯企业占据了市场的主导地位。随着技术的持续进步和用户需求的日益多样化,选择音视频服务提供商的标准也越来越个性化&am…...
红黑树介绍及插入操作的实现
🎉个人名片: 🐼作者简介:一名乐于分享在学习道路上收获的大二在校生 🙈个人主页🎉:GOTXX 🐼个人WeChat:ILXOXVJE 🐼本文由GOTXX原创,首发CSDN&…...
[linux初阶][vim-gcc-gdb] TwoCharter: gcc编译器
目录 一.Linux中gcc编译器的下载与安装 二.使用gcc编译器来翻译 C语言程序 ①.编写C语言代码 ②翻译C语言代码 a.预处理 b.编译 c.汇编 d.链接 ③.执行Main 二进制可执行程序(.exe文件) 三.总结 一.Linux中gcc编译器的下载与安装 使用yum命令(相当于手机上的应用…...
单例设计模式(2)
单例设计模式(2) 单例模式存在的问题 单例对 OOP 特性的支持不友好 oop的特性:封装、继承、多态、抽象;以Id生成器代码为例,如果未来某一天,我们希望针对不同的业务采用不同的 ID 生成算法。比如&#x…...
boost::asio 启用 io_uring(Linux 5.10)队列支持
欲启用 boost::asio 对于 io_uring 的支持,这需要以下几个先决条件; 1、boost 1.78 及以上发行版本 Revision History - 1.78.0 (boost.org) 2、Linux kernel 5.10 及以上发行版本 3、在预定义头文件(stdafx.h)、或编译器预定义…...
Android 自定义坐标曲线图(二)
Android 自定义坐标曲线图_android 自定义曲线图-CSDN博客 继上一篇文章,点击折线图上的点,显示提示信息进行修改,之前通过回调,调用外部方法,使用popupwindow或dialog来显示,但是这种方法对于弹框显示的位…...
淄博企业网站建设价格/怎样做一个网页
最近在给内部使用的zabbix配置告警发送,要求是使用企业微信群聊机器人发送告警信息到群里,因为企业号和公众号需要的开发信息较多,又不好找,而配置机器人发送告警只需要机器人的webhook地址即可。 步骤: 1、 在zabbi…...
制作网站需要的服务器/长春seo排名优化
以前在学校学习C语言的时候一直搞不懂那个共用体union有什么用的。工作之后才发现它的一些妙用,现举例如下:1. 为了方便看懂代码。比如说想写一个3 * 3的矩阵,可以这样写:[ 注:下面用红色部分标记的地方是后来添加上去…...
专业型企业网站有哪些/广东网站营销seo费用
传送门 分析 从1道m进行匹配,找到第一个不能继续匹配的点即可 代码 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cctype> #include<cmath> #include<cstd…...
门户网站直接登录系统/如何网页优化
案例介绍本章节主要用java实现;方法调用指令、返回指令、解析方法符号引用、参数传递等。实现新的指令后我们的虚拟机就可以执行稍微复杂的运算并输出结果。从调用的角度来看,方法可以分为两类:静态方法(或者类方法)和实例方法。静态方法通过…...
珠海做网站优化的公司/万网阿里云域名查询
怪自己大学C语言学的不扎实,下面的程序看了好久才破解,大神见谅,写下总结吧 程序先贴出来: 定义如下:子程序如下:实际调用如下刚开始看的时候,死活没搞懂,后来通过验证什么的弄懂了&…...
小程序游戏制作/东莞百度seo排名
作者|yawn Lauhttp://jvm123.com/2019/08/springboot-activiti.html依赖:新建springBoot项目时勾选activiti,或者在已建立的springBoot项目添加以下依赖:org.activitiactiviti-spring-boot-starter-basic6.0.0配置:数据…...