‘壹’ JobScheler的使用和原理
JobScheler 主要用于在未来某个时间下满足一定条件时触发执行某项任务的情况,涉及的条件可以是网络、电量、时间等,例如执行特定的网络、是否只在充电时执行任务等。
JobScheler类负责将应用需要执行的任务发送给框架,以备对该应用Job的调度,是一个系统服务,可以通过如下方式获取:
JobInfo是传递给JobScheler类的数据容器,它封装了针对调用应用程序调度任务所需的各种约束,也可以认为一个JobInfo对象对应一个任务,JobInfo对象通过JobInfo.Builder创建。它将作为参数传递给JobScheler:
JobInfo.Builder是JobInfo的一个内部类,用来创建JobInfo的Builder类。
JobService是JobScheler最终回调的端点,JobScheler将会回调该类中的onStartJob()开始执行异步任务。它是一个继承于JobService的抽象类,做为系统回调执行任务内容的终端,JobScheler框架将通过bindService()方式来启动该服务。因此,用户必须在应用程序中创建一个JobService的子类,并实现其onStartJob()等回调方法,以及在androidManifest.xml中对它授予如下权限:
注意在AndroidManifest.xml中添加权限
当任务开始时会执行onStartJob(JobParameters params)方法,如果返回值是false,则系统认为这个方法返回时,任务已经执行完毕。如果返回值是true,那么系统认为这个任务正要被执行,执行任务的重担就落在了你的肩上。当任务执行完毕时你需要调用jobFinished(JobParameters params, boolean needsRescheled)来通知系统。
当系统接收到一个取消请求时,系统会调用onStopJob(JobParameters params)方法取消正在等待执行的任务。很重要的一点是如果onStartJob(JobParameters params)返回false,那么系统假定在接收到一个取消请求时已经没有正在运行的任务。换句话说,onStopJob(JobParameters params)在这种情况下不会被调用。
需要注意的是这个Job Service运行在主线程,这意味着你需要使用子线程,handler,或者一个异步任务来运行耗时的操作以防止阻塞主线程。
Google官方的Sample: https://github.com/googlearchive/android-JobScheler
JobScheler是一个抽象类,它在系统框架的实现类是android.app.JobSchelerImpl
执行的入口是JobScheler.scheler,其实是调了JobSchelerImpl中的schele方法;然后再调了mBinder.schele(job)。这个mBinder就是JobSchelerService,通过Binder跨进程调用JobSchelerService。
最后调用到JobSchelerService中的schele方法:
接着发送MSG_CHECK_JOB消息,消息处理的地方是
接着执行JobHandler中的 maybeRunPendingJobsH 方法,处理相应的任务
availableContext是JobServiceContext,即ServiceConnection,这个是进程间通讯ServiceConnection,通过调用availableContext.executeRunnableJob(nextPending)方法,会触发调用onServiceConnected,看到这里应该明白了,onServiceConnected方法中的service就是Jobservice,里面还用了WakeLock锁,防止手机休眠。
接着,通过Handler发消息,调用了handleServiceBoundH()方法。
从上面源码可以看出,最终是触发调用了JobService中的startJob方法。
从源码看,设置的内容应用于 JobStatus ,例如网络限制
而在JobSchelerService类,相关的状态控制在其构造函数里:
例如网络控制类ConnectivityController类
当网络发生改变时,会调用updateTrackedJobs(userid)方法,在updateTrackedJobs方法中,会判断网络是否有改变,有改变的会调mStateChangedListener.onControllerStateChanged()方法;然后调用了JobSchelerService类中onControllerStateChanged方法:
接着也是处理MSG_CHECK_JOB 消息,和上文一样,最终触发调用了JobService中的startJob方法。
JobSchelerService是一个系统服务,即应该在SystemServer启动的。阅读SystemServer的源码:
run 方法如下:
接着看 startOtherServices()
因此,在这里就启动了JobSchelerService服务。
1. android 性能优化JobScheler使用及源码分析
2. Android 9.0 JobScheler(一) JobScheler的使用
3. Android 9.0 JobScheler(二) JobScheler框架结构简述及JobSchelerService的启动
4. Android 9.0 JobScheler(三) 从Job的创建到执行
5. Android 9.0 JobScheler(四) Job约束条件的控制
6. 理解JobScheler机制
‘贰’ 《深入理解react》之调度引擎——Scheler
深入理解react
在react 18版本发布以来的近两年时间里,许多伙伴都体验到了并发模式带来的爽感,createRoot()的使用让应用有了更流畅的体验。而这一切的核心,便是react执行流中的调度引擎——Scheler。调度,这个概念在计算机行业中广泛存在,无论是操作系统、浏览器还是大型应用,都离不开调度任务的需求。Scheler,作为独立的包,不仅可以在react中使用,更可以在任何其他库中发挥作用,其简洁的源码使深入理解react成为可能。
为何需要调度器?首先是为了解决卡顿问题。在js引擎和渲染绘制都在同一线程执行的情况下,如何保证60帧的刷新频率不被CPU密集型任务阻塞?其次,react会生成具有优先级的任务,优先级高的任务可能在后面产生,调度器能确保优先级高的任务优先执行,以提升用户体验。
Scheler通过暴露的方法如unstable_scheleCallback,可以按照优先级的高低顺序调度任务,并保证异步执行。在实际体验中,我们可以创建工程来测试Scheler的执行时机,发现它会遵循优先级顺序,优先执行高优先级任务,并在下一个宏任务中异步执行。
源码解析中,小根堆作为关键数据结构,用于维护优先级队列。Scheler使用小根堆来管理任务,优先级最高的任务始终处于堆顶。优先级的动态调整确保了任务在调度过程中的灵活排序。例如,随着时间推移,新任务的优先级会逐渐提高,使得原有任务在下一个周期中优先执行。
Scheler的核心逻辑在工作循环中体现,通过合理调度不同优先级的任务,既不阻碍UI绘制,又能高效执行任务。对于大任务,用户可以通过拆分策略,将其划分为多个小任务,以避免阻塞UI,实现流畅的用户体验。
最后,Scheler在react中扮演着关键角色,通过合理的任务调度,确保应用流畅运行。深入理解Scheler,将为深入理解react提供坚实的基础。关注专栏,获取更多react相关知识。