文章主题是“单线程模型下怎样确保 UI 的流畅性”。该论题针对的是 Flutter 功能原理翻开的,可是 dart 言语便是 js 的延伸,许多概念和机制都手势舞教程视频慢动作线程是什么意线程的几种状况相同的。具体前端不细聊。此外 js 也是单线程模型,在界面展示和 IO 等方面和 dart 类似。所以结合比照讲一下,协助收拾和类比,愈加简略把握本文的主题,和常识的横向拓展。

先从前端视点启航,动画分析下 event loop手势语 和作业部队模型。再从 Flutter 层启航聊聊 dart 侧的作业部队和优先级排序同步异步使命之间的联络。

一、单线程模型的规划

1. 最根底的单线程处理简优先级矩阵有两个重要维度是略使命

假定有几个使命:

  • 使命动画片少儿1: “姓名:” + “杭城小刘”
  • 使命2: “手势舞怎样学根底年岁:” + “1995” + “02” + “20”
  • 手势舞怎样学根底务3: “巨细:” + (2021 – 1995 + 1)
  • 使命4: 打印使命1、2、3 的作用

在单线程中实施,代码或许如下:

//c
void mainThread () {
strin前端结构势舞g手势舞怎样学根底 name = "姓名:" + "杭城小刘";
stri动画图片头像ng birthday = "年岁:" + "1995" + "02" + "20"
int age = 2021 - 1995 + 1;
printf("个人信息为:%s, %s,手势暗码图画大全 巨细:%动画片汪汪队d", name.优先级队伍c_str(), birthday.c_str(), age);
}

线程开端实施使命,依照需求,单线程依次实施每个使命,实施完毕后线程立动画片少儿刻退出。

从 Flutter 和前端视点启航,聊聊单线程模型下怎样确保 UI 流畅性

2. 线程工作进程中来了新的使命怎样处理?

问题1 介绍的线程模型太简略太动画头像理想了,不或动画专业许从一开端就 n 个使命就承认了,大多数状况下,会接纳到新的 m 个使命。那么 section1 中的规划就无法满前端开发需肄业什么足该需求。

**要在线程工作的进程中,能够承受并实施新的使命,就需求有一个作业循环机制。**最根底的作优先级是什么意思业循环能够想到用一个循环来完毕。

// c++
int动画图片头像 getInput() {
int inp线程池动画制造软件原理ut = 0;
cout&l手势语t动画;&优先级排序lt; "请输入一个数";
cin>>input;
return input;
}
vo动画片汪汪队id mainThread () {
while(true) {
int input1 = getInput();
int inp前端结构u线程池创立的四种t2前端训练组织 = getInput();
int sum = input1 + input2;线程池原理
pri前端开发nt(前端工程师"两数之和为:%d", sum);
}
}

相较于第一版线程规划,这一版做了以下手势改善:

  • 引进了循环机制,线程不会做完作业马上退出。
  • 引进了作业。线程一开端会等候用户输入,等候的时分线程撕裂者线程处于暂停状况,当用户输入完毕,线程得到输入的信息,此时线程被激活。实施相加的操作,终究输出手势舞怎样学根底作用。不断的等动画头像候输入,并核算输出。

从 Flutter 和前端视点启航,聊聊单线程模型下怎样确保 UI 流畅性

3. 处理来自其他线程的使命

真实环境中的线程模块远远没有这么简略。比方浏览器环境下,线程或许正在制造,或许会接纳到1个来自用户鼠标点击的作业,1个来自网优先级表络加载 css 资源完毕的作业等等。第二版线程模型虽然引进了作业循环机制,能够承受新的作业使命,可是发现没?这些使命之来自线程内部,该规划是无法承受来自其他线程的使命的。

从 Flutter 和前端视点启航,聊聊单线程模型下怎样确保 UI 流畅性

从上图能够看出,手势烘托主线程会一再接纳到来自于线程池面试题 IO 线程的一些作业使命,当接遭到的资源加载完毕后的音讯,则烘托线程会开端 DOM 解析;当接前端开发收到来自鼠标点击的音讯,烘托主线程则会实施绑定好的鼠标点击作业脚本前端开发需肄手势辨认业什么(js)来处理作业。

需求一个合理的数据结构,来存放并获取其他线程发送的音讯?

音讯部队这个词我们都听过,在 GUI 体系中,作业部队是一个通用处理计划。

从 Flutter 和前端视点启航,聊聊单线程模型下怎样确保 UI 流畅性

音讯部队(作业部队)是一种合理的数据结构。要实施的使命添加到部队的尾部,需求实施的任动画专业务,从部队的头部取出。

有了音讯部队之后,线程模型得到了晋级。如下:

从 Flutter 和前端视点启航,聊聊单线程模型下怎样确保 UI 流畅性

能够看线程池的七个参数出改造分为3个进程:

  • 构建一个音讯部队
  • IO 线程发生的新使命会被添加到音讯部队的尾部
  • 烘托主线程会循环的从音讯部队的头部手势舞怎样学根底读取使命,施手势舞行使命

伪代码。结构部队接口部分

clas前端开发是干什么的s TaskQueue {
public:
Ta动画片少儿sk fetchTask (); // 从部队头部取出1个使命
void addTask (Task task); /线程和进程的差异是什么/ 将使命刺进到部队尾部
}

改造主线程

TaskQueue taskQueue;
void processTask ();
void mai优先级矩阵有两个重要维度是nThre优先级和劣后级的差异ad () {
while (tr动画片猫和老鼠ue) {
Task task = taskQ线程池创立的四种ueue.fetchTask();
processTask(t动画片少儿小猪佩奇ask);
}
}

IO 线程

void handleIOTask () {
Task clickTa线程池原理sk;优先级是什么意思
taskQueue.addTask(clickTask);
}

Tips: 作业部队是存线程在多线程访问的状况,所以需求加锁。

4. 处理来自其他线程的使命

从 Flutter 和前端视点启航,聊聊单线程模型下怎样确保 UI 流畅性

浏览器环境中, 烘托进程前端学什么常常线程池创立的四种接纳到来自其他进前端面试题程的任手势务,IO 线程专门优先级调度算法用来接纳来自其他进程传递来的消优先级英文息。IPC 专门处理迈进前端开发是干什么的程间的通讯。

5.线程池原理 音讯部队中的使命类型

音讯部队中有许多优先级调度算法音讯类型。内部音讯:如鼠标翻滚、点击、移动、宏使命、微使命、文件读写、优先级c言语定时器等线程安全等。

音讯部队中还存在许多的与页面相关的作业。如 JS 实施、DOM 解析、手势意义图解大全前端结构款式核算、布局核算、CSS 动画等等。

上述作业都是在烘托主线程中实施的,因此编码时需注意,尽量减小这些作业所占用的时长。

6. 怎样安全退出

Chrome手势舞 规划上,线程池的七个参数承认要退出其时页面时,页面主线程会设置一个动画片少儿小猪佩奇退出标志的变量,每次实施动画片小猪佩奇手势语手势舞教程视频慢动作1个手势使命时,判别该标志。假定线程池原理设置了,则连续使命,退出线程

7. 单线程的缺陷线程的几种状况

作业部队的特点是先进先出,后进后出。那后进的使命或许会被前面的使命由于实施动画片少儿小猪佩奇时间过长而堵塞,等候前面的线程使命实施完毕才能够实施后边手势意义图解大全的使命。这样存在2个问题。

  • 怎样处理高优先级的使命

    假定要监控 DOM 节点的改动状况(刺进、删去线程安全、批改 innerHTML),然后触发对应的逻辑。最根底的做法便是规划一套监听接口,当 DOM 改动时,烘托引擎同步调用这些接口。不过这姿态存在很大的问题,便是 DOM 改动会很一再。假定每次 DOM 改手势舞动都触发对应的 JS优先级最高的运算符 接口,则该使命实施会很长,导致动画实施功率的下降

    假定将这些 DOM 改动做为异步音讯,假定音讯部队中。或许会动画片汪汪队存在由于前面的使命在实施导致其时的 DO线程池创立的四种M 音讯不会被实施的问题,也便是影响了监控的优先级表前端开发需求把握什么技能前端

    怎样权衡功动画图片头像率和实时性?微使命 便是处理该类问题的。

    一般,我们把音讯部队中的使命成为宏使命,每个宏使命中都包括一个微使命部队,在实施宏使命的进程线程池创立的四种中,假定 DOM 有改动优先级和劣后级的差异动画图前端开发是干什么的片头像,则该改动会被添加到该宏使命的微使命部队中去,这姿态功率问题得以处理。

    当宏使命中的主要功能实施完毕欧,烘托引擎会实施微使命部队中的微使命。因此实时性问题得以处理

  • 怎样处理优先级和劣后级的差异动画片大全少儿悉数免费单个使命实施时间过长的问题

    从 Flutter 和前端视点启航,聊聊单线程模型下怎样确保 UI 流畅性

    能够看出线程池原理,假定 JS 核算超时导致动画 paint 超动画专业时,会构成卡顿。浏览器为避免该问题,选用 callbac线程池原理k 回调的规划来躲避,也便是让手势意义图解大全 JS 使命延迟实施。

二、 flutt线程池原理er线程撕裂者 里的单线程和进程的差异是什么线程模型

1. ev手势意义图解大全ent loop 机制

Dart 是单线程的,也便是代码会有序实施。此外 Dart 作为 Flutter优先级c言语 这一 GU前端学什么I 结构的开发言语,必定支撑异步。

一个 Flu前端面试题势舞视频tter 运用包括一个或多个 iso线程池原理late,默许办法的实施都是在 main isolate 中;一个 isol线程池原理ate 包括1手势意义图解大全个 E优先级调度算法vent loop 和1个 Task qu手势意义图解大全eue。其间,Task queue 包括1个 Event queue 作业部队和1个 MicroTask queue 微使命部队前端开发需求把握什么技能。如前端面试题下:

从 Flutter 和前端视点启航,聊聊单线程模型下怎样确保 UI 流畅性

为什么需求异步?由于大多数场景下 运用都并不是一向优先级c言语在做运算。优先级c言语比方一边线程安全等候用户的输入,输优先级是什么意思入后再去参前端开发需肄业什么与运算。这便是一个 I手势辨认O 的场景。所以单线程能够再等候的时分做其他作业,而当真实线程池原理需求处理运算手势暗码图画大全的时分,再去处理。因此虽是单线程,可是给我们动画头像的感受是伙伴在做许多作业(空闲的时分去做其他作业)

某个使命触及 I线程池面试题O 或许异步,则主线程会先去做其他需手势求运算的作业,这个动作是靠 event loop 驱动手势舞视频的。和 JS 相同,dart 中存储作业动画制造软件使命的人物是作业部队 event线程 queue。

Event queue 担任存储线程池的七个参数需求实施的使命作业,比方 DB 的读取。

Dart 中存在2优先级线程的几种状况队伍个部队,一个微使命部队(Mic优先级排序rota动画sk Queue)、一个作业部队(Event优先级c言语 Queue)。

Event loop 不断的轮询,先判别微使命部队是否为空,从部队头部前端和后端的差异取出需求实施的使命。假定微使命部队为空,则判手势舞视频别作业部队是否为空,不为空则从头手势部取出作业(线程池面试题比方键盘、IO、网络作业等)前端开发需求学什么手势辨认然后在主线程实前端开发是干什么的行其回调函数,如下:

从 Flutter 和前端视点启航,聊聊单线程模型下怎样确保 UI 流畅性

2. 异步使命

优先级c言语使命,即在一个很短的时间内就会结优先级排序优先级的异步使命。微使命在作业循环中优先级最高,只需微使命部队不为空,作业循环就不断实施微使命,后续的作手势舞视频业部队中的使命继续等候。微使命部队可由 schedu动画专业leMicroTask 创立。

一般状况,微使命的运用场景比较少。F动画片猫和老鼠lutter 内部也在比方手势辨认、线程池创立的线程是什么意思四种文本输入、翻滚视图、保存页面作用等需求高优实施使命的场景用到手势了微前端开发需求把握什么技能使命。

所以,一般需求下,异步使命我们运用优先级较低优先级英文的 Event Queue。动画头像比方 IO、制造、定时器等动画片少儿,都是经过作业部队驱动主线程来实施的。

Dart 为 Event Queue 的使命供应了一层封装,叫做 Future。把一手势语个函数体放入 Future 中,就完毕了同步使命到异步使命的包装(类似于 iOS 中经过 GCD 将一个使命以同步、异步前端动画头像交给某个部队)。Future 具有链式调用的才能手势意义图解线程池创立的四种大全,能够在异步实施完毕后实施其他使命(函数)。

看一段具体代码:

void main() {
print('normal task 1');
Future(() => print线程撕裂者('Task1 Future 1'));
print('normal task 2');
Future((优先级最高的运算符) => print('Task1 Future 2'))
.the手势舞n((value) => print("subTask 1"))
.then((valu优先级矩阵有两个重要维度是e) => pr动画图片头像int("subTask优先级 2"手势暗码动画大放映))优先级和劣后级的差异;
}
//
lbp@MBP  ~/Des动画头像ktop  dart index.手势暗码图画大全dart
no线程池面试题rmal动画图片头像 task 1
normal tas前端k手势数字1到10 2
T线程池原理as优先级排序k1优先级表 Future 1
Task1 Fu线程池面试题ture 2
subTask 1
subTask 2

main 办法内,先添加了1个一般同步线程池的七个参数使命,然后以 Future 的办法添加了1个异步使命,Dart 会将异步使命加入到作动画片少儿业部队优先级表中,然前端面试题后了解回来。后续代码继续以同步使命的办法实施。然后再添加前端开发了1个一般同步使命。然后再以 Fu前端手势暗码图画大全开发是干什么的ture 的办法添加了1个异步使命,异步使命被加入到优先级英文作业部队中。此时,作业部队中存在2个异步使命,Dart 在作业部队头部取出1个使命以同步的办法实施,悉数实施(先进先出)完毕后再实施后续的 then。

F优先级c言语uture 与 then 共用1个作业循环。假定存在多个 then,则依照次序实施。

例2:

void main() {
Future(() => print('Task1 Future 1'));
Future(() => print('Task1 Future 2'));
Future(() => print('Task1 Futur手势舞e 3优先级是什么意思'))
.then((_) => print('subTask 1 in Future 3'));
Fu线程池创立的四种ture(() =&优先级调前端开发是干什么的度算法gt; null).then((_) => print('subTask 1 in empty Fu动画大放映ture'));
}
lbp@MBP  ~/Desktop  dart index.dart
Tas手势数字1到10k1 F优先级最高的运算符uture 1
Task1 Fut优先级英文ure 2
Task1 Future 3
subTask 1 in Future 3
subTask 1 in e动画片小猪佩奇mpty Future

main 办法内,Ta动画片汪汪队sk 1 增手势辨认加到 Future 1中,被 Dart 添加到 Event线程池原理 Queue 中。Task 1 添加到 Future 2中线程撕裂者,被 Dart 添加到 Event Queue 中。Task 1 增前端和后端的差异加到 Future 3中,被 Dart 添加到 Event Queue 中,subTask 1 和 Task线程的几种状况 1 共用 Event Queue。Future 4中使命为空,所以 then 里的代码会被加入到 Microtask Queue,以便下一轮作动画专业业循环中被实施。

归纳比方

void main() {
Future动画(() =&前端学什么gt; print('动画Task1 Future 1'));
Futu优先级和劣后级的差异re fx = Future(() => null);
Futur线程的几种状况e(线程池(手势舞教程视频慢动作) => print("Task1 Future 3"优先级矩阵有两个重要维度是)).then((value) {
print("subTask 1 Fut优先级表ure 3"手势);
sc动画片少儿heduleMicrotask((动画制造软件) =>手势暗码 print("Mi动画片少儿小猪佩奇crota优先级队伍sk线程和进程的差异是什么 1"));
}).then((value) =>前端开发需求把握什么技能 print("subTask 3 Fu手势舞怎样学根底ture 3"))优先线程池面试题;
Fu前端和后端哪个薪酬高ture(() =>动画片少儿 print("Task1 Future 4"手势舞怎样学根底)动画片猫和老鼠)
.then((value) => Future(() =>前端学什么 print("sub subTask 1 Future 4")))
.then((va前端开发是干什么的lue) => print("sub subTask 2 Future 4"手势辨认));
Future(() => print优先级调度算法("Task1线程池面试题 Future 5"));
fx.the线程安全n((value) => print(线程池面试题"前端面试题Task1 Future 2"));
sch动画片小猪佩奇eduleMicrotask(() => print("Microtask 2"));
print(手势舞"norm线程安全al Task");
}
lbp@MBP  ~/Desktop  dart index.dart
normal Task
Microt手势语a动画片少儿小猪佩奇sk 2
Tas动画制造软件k1 Future 1
Task1前端学什么 Future 2
Task1 Future 3
subTask 1 Futu手势舞教程视频慢动作re 3
subTask 3 Future 3
Microtask 1
Task1 Future 4手势舞
T优先级调度算法ask1 Future 5
sub subTask 1 Futur手势意义图解大全e 4
sub subTask 2 Futu手势舞视频re 4

说明:

  • Event Lo优先级c言语op 优先实施 ma线程池面试题in优先级最高的运算符 办法同步使命,再实施微使命,最优先级表终实施 Even前端和后端的差异t Queu手势数字1到10e 的异步使命。所以 normal Task 先实施
  • 同理微使命 Microtask 2 实施
  • 其次,Event Qu优先级英文eue FIFO,Task1 Future 1 被实施
  • fx Future 内部为空,所以 then 里的内容被加手势意义图解大全到微使命部队中去,微使命优先级最高,所以 Task1 F前端训练组织ut手势舞怎样学根底ur前端和后端的差异e线程安全 2动画大放映 被实施
  • 其次,Task1 Future 3 被实施。由于存在2个 the前端开发需肄业什么n,先实施第一个 then 中的 subTask 1 Future 3,然后遇到微使命,所以 Microtask 1 被添加到微使命部线程安全队中去,等候下一次 Event Loop 到来时触优先级矩阵有两个重要维度是发。接着实施第二个 then 中的 subTas优先级c言语k 3 Future 3。跟着动画片猫和老鼠下一次 Event手势舞怎样学根底 Loop 到来,Microtask 1 被实施
  • 其次优先级,Task1 Future 4 被施动画片少儿行。随后的第一个 then 中的使命动画又是被 Future 包装成一个异步使命,被添加到 Event Queue 中,第二个 t手势辨认hen 中的内容也被添加到 Event Queue 中。
  • 接着,实施 Task1 Future 5。本次作业循环完毕
  • 等下一轮作业循环到来动画大放映,打印部队中的 sub subTask 1 Future 4、sub subTask 1 Future 5.

3. 异步函数

异步函数的作用在将来某个时间才回来,所以需求回来一个 Futu优先级矩阵有两个重要维度是re 政策,手势语供调用者运用。调用者根据需求,判别是在 Future 政策上注册一个 then 等 Future 实施线程的几种状况体完毕前端面试题后再前端学什么进行异步处理,仍是同步等到 Future 实施结前端面试题束。F前端开发是干什么的uture 政策假定需求同步等候,则需求在调用处添加 await,且 Future 地动画片猫和老鼠址的函数需求运用 async 关键字。

await 并不是同步等候,而是异步等候。Event Loop 会将调用体地址的函数也当作异步函数,将等候句子的上下文全体添加到 Event Queue 中,一旦回来,优先级Event L前端开发oop 会在 Event Queue 中取出上下文代码,等候的代码继续实施。

awai优先级英文t 堵塞的是其时上下文的后续代码动画大放映实施,并不能堵塞其调用栈上层的后续代码实优先级表

void优先级表 main() {
Future(() => print('Task1 Future 1'))
.then((_) async => await Future(() => print("su动画大放映bTask 1前端开发需求学什么 Future 2")))
.then((_手势语) => print("subTask 2 Future 2"))线程的几种状况;
Future(() => print('Task1 Future 2'));
}
lb手势数字1到10p@MBP  ~/Des优先级队伍k动画头像top  dart ind线程的几种状况ex动画片少儿.dart
Task1 Futur动画片猫和老鼠e 1
Task1 Future 2
sub前端开发需求学什么Task 1 Future 2
s动画片少儿ubTask 2 Future 2

解析:

  • F优先级英文u优先级英文ture 中的 Task1 Future 1 被添加到 Event Queue 中。其次遇到第线程是什么意思一个 then,then 里边是 F优先级队伍uture 包装的异步手势暗码图画大全使命,所以 Future(() =&g手势暗码t; print("subTask 1 Future 2")) 被添加到 Eve动画片汪汪队nt Queue 中,地址的 awai线程t 函数也被添加到了 Event Q线程的几种状况ueue 中。第二个 then 也被添加前端开发是干什么的到 Event Queue 中
  • 第二个 Future 中的 ‘Task1 Future 2 不会被 await 堵塞,由于 await 是异步等候(添手势舞视频加到 Event Queue)。所以实施 ‘Task1 F动画片汪汪队uture 2。随后实施 “subTask 1 Future 2,接着取前端面试题出 await 实施 subTask 2 Future 2

4. Isolate

Dart 为了运用多核 CPU,将 C前端PU 层面的布满型核算进行了阻隔规划,供应了多线程机制,即 Isolate。每个 Isolate 资源阻隔,都有自己的 Event Loop 和 Event Queue动画片少儿小猪佩奇前端开发Microtask Qu手势数字1到10eue。Isolate 之间的资源共享经过音讯机制通讯(和进程相同)

运用很简略,创立时需求传递一个参数。

v前端训练组织oid coding(language) {
print("hello " + language);
}
v前端和后端的差异oid main() {
Isolate.spawn(coding, "Dart");
}
lbp@MBP  ~/De优先级sktop 优先级矩阵有两个重要维度是 dart ind优先级动画片少儿小猪佩奇英文ex.dart
hello Dart

大多数状况下,不仅仅需求并发实施。或许动画还需动画求某个 Isolate 运算完毕后将作用奉告主 Isol优先级矩阵有两个重要维度是ate。能够经过 Iso线程池late 的管道(SendPort)完毕音讯通讯。能够在主 Isolate 中将管道动画专业作为参数传递给子 Isolate,当子 Isolate 运算完毕后将作用运用这个管道传递优先级英文给主 Is手势舞教程视频慢动作olate

void coding(SendPort port) {
const sum = 1 + 2;
// 给调用方发送作用
port.send(sum);
}
void main() {
testIsolat优先级最高的运算符e();
}
testI优先级是什么意思so手势暗动画专业late() async {线程和进程的差异是什么
ReceivePort receivePort = Re动画大放映ceivePort(); // 创立管道
Isolate isolate = aw线程池的七个参数ait Isolate.spa线程池原理wn(coding, receivePort.sendPor优先级最高的运算符t); // 创立 Isolat动画片少儿e,并传递发送管道作为参数
// 监听音讯
receive前端学什么Port.listen((message) {
print("da手势暗码ta: $messag手势e");
receive前端面试题Port.close();
isolate?.kill(priority: Isolat线程池创立的四种e.imm手势舞ediate);
isolate = null;
});
}
lb动画大放映p@MBP  ~/前端结构Desktop  da手势语r前端开发需肄业什么t index前端和后端哪个工资高.dart
data: 3

此外 Flutter 中供应了实施并发核算使命的快捷办法-compute 函数。其内部对 Isolate 的创立和双向通讯进行了封装。

实际上,业务开发中运用 comput优先级队伍e 的场景很少,比方 JSON 的编解码能够用线程池的七个参数 compute前端面试题

核算阶乘:

int testCom线程是什手势么意思pute() async {
return await compute(线程syncCalcuateFactorial, 100);
}
int syncCalcuateFactorial(upperBo前端开发是干什么的unds) => upperB优先级矩阵有两个重要维度是ounds < 2
? up优先级矩阵有两个重要维度是perBoun优先级和劣后级的差异ds
: upperBounds * syncCalcuateFact动画线程是什么意思片汪汪队orial(upp动画片少儿小猪佩奇erBounds - 1);

总结:

  • Dart 是单线程动画图片头动画片大全少儿悉数免费的,但经过作业循环能够完毕异步
  • Future 是异步使命的封装,借助于前端开发需求学什么 await 与 async,我们能够经过作业循动画环完毕非堵塞的同步等候
  • Isolate优先级和劣后级的差异 是 Dart 中的多线程,能够完毕并发,有自己的作前端开发业循环与 Queue,独占资源动画片猫和老鼠。Isol手势意义图解大全at优先级和劣后级的差异e 之间能够经过音讯机制进行单向通讯动画手势舞怎样学根底专业,这些传递手势舞视频的音讯经过对方的作业循动画环驱动对方进行异步处理。
  • flutter 供线程安全给了 CPU 布满运算的 c优先级排序ompute 办法,内部封装了 Isolate 和 Isolate 之间的通讯
  • 作业部队、作业循环的概念在线程安全线程安全 GU手势意义图解大全I 体系中非常重要,几乎在前端、Flutter、iOS、Android 乃至是 NodeJS 中都存动画在。