成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

解讀京東零售云mPaaS中Flutter中熱重載原理

云計算 PaaS
熟悉JS的同學,可能會嗤之以鼻,在N年前就已經(jīng)用上熱重載了,但是對客戶端開發(fā)人員來說,簡直是福音。

本文要點:

  • 了解京東零售云mPaaS中Flutter的熱重載原理,有利于日常開發(fā)中高效排查問題;
  • 掌握如何調(diào)試斷點Flutter工具鏈源碼;

一、前言

1.1 熱重載是什么?

熟悉JS的同學,可能會嗤之以鼻,在N年前就已經(jīng)用上熱重載了,但是對客戶端開發(fā)人員來說,簡直是福音。

那先來看下Flutter官方的定義:

  • Flutter’s hot reload feature helps you quickly and easily experiment, build UIs, add features, and fix bugs. Hot reload works by injecting updated source code files into the running
  • Dart Virtual Machine (VM). After the VM updates classes with the new versions of fields and functions, the Flutter framework automatically rebuilds the widget tree,
  • allowing you to quickly view the effects of your changes.

簡單來說,就是通過將修改后的源代碼文件注入到正在運行的 Dart 虛擬機來實現(xiàn),注入之后, Flutter 會自動重新構(gòu)建 widget 樹。

1.2 為什么需要熱重載?

程序猿在刀耕火種的時代,開發(fā)調(diào)試是這樣子的:

當項目不大,人數(shù)不多的情況下,畫面是非常和諧的,效率也是毋庸置疑的高效。但現(xiàn)實是,在大公司,項目往往很大,編譯巨慢無比,同時開發(fā)人員眾多,有著非常嚴格的流程制度,導(dǎo)致看起來本沒有問題的開發(fā)調(diào)試流程,變得異常的痛苦,降低了個體的效率,這里強調(diào)下,指的是個體的效率,個人認為越是完善的流程體系,對個體的約束往往越強,但從團隊的角度去看待效率,一定是能 1+ 1 大于 2 的。

而此時的心情是這樣子的:

[[424264]]

而有了熱重載,開發(fā)調(diào)試是這樣子的:

心情也就成這樣子的:

[[424266]]

1.3 拋出問題

從熱重載定義來看,不少人腦子里蹦出不少跟我一樣的疑惑:

  • 怎么知道哪個文件被修改?
  • 修改的源代碼到底被轉(zhuǎn)成什么?
  • 修改的源代碼是怎么注入到Dart虛擬機的?
  • Flutter框架又是怎么觸發(fā)widget重繪的?

同時在日常使用熱重載的過程中,也會碰到不少這樣那樣的疑惑:

  • 為什么運行flutter attach后還需要手動輸入r來熱重載?
  • 手動敲r,這么無(gou)語(shi)的設(shè)計,我們能做成自動化嗎?

當你在網(wǎng)上看過大量熱重載文章后,又衍生了額外的問題:

  • 嘗試去探索源碼時,case太多,怎么能模擬真實環(huán)境?能否斷點調(diào)試Flutter源碼?
  • 熱重載看著跟動態(tài)化很像,那能否運用在動態(tài)化技術(shù)上?

不急,本文會對上述疑問進行一一解答。

二、dart的熱重載

由于Flutter采用dart作為開發(fā)語言,我們先從dart角度來驗證下熱重載。

2.1 編寫驗證demo

考慮到dart執(zhí)行完會關(guān)閉當前進程,我們寫了個定時器來保證進程存活,同時能看到熱重載效果。

2.2 開啟VMService

終端下執(zhí)行 dart --enable-vm-service main.dart,其中的main.dart為2.1中代碼文件:

可以看到終端會不斷輸出"Hello JDFlutter"的字符。

2.3 執(zhí)行熱重載

我們將main.dart文件中打印日志修改為”Hello JD”,同時打開終端輸出的Observatory鏈接地址,如下:

找到我們main.dart的Isolate(讀者可以簡單理解為是dart中的線程,只不過Isolate沒有共享內(nèi)存),圖中紅圈部分,進入后找到Reload Source:

點擊Reload Source后,終端開始輸出”Hello JD”的字符,完成了一次熱重載過程,如下圖:

2.4 自動化熱重載

還是以上面為例子基礎(chǔ)例子,我們加入文件監(jiān)聽,并且通過發(fā)送消息給vm_service來實現(xiàn)熱重載,代碼如下:

直接運行 dart --enable-vm-service main.dart,期間修改”Hello JDFlutter”為”Hello JD”,運行結(jié)果如下:

可以看出,我們成功實現(xiàn)了自動化熱重載,上述代碼跟Dart虛擬機通信步驟如下:

  • 獲取Dart VM的websocket服務(wù)URI
  • 通過URI連接上Dart VM的service
  • 通過service獲取Dart VM
  • 通過Dart VM獲取isolateId
  • 通過service重載指定isolateId的任務(wù)

2.5 Dart虛擬機可做的事情

到這里,大家可以放飛自我,Dart Service提供了大量對外協(xié)議,包含斷點、獲取虛擬機狀態(tài),性能等協(xié)議,可以參考:Dart虛擬機服務(wù)接口。

三、Flutter的熱重載

Flutter的熱重載,本質(zhì)是在封裝dart熱重載并且對不同的設(shè)備啟動安裝加載等流程,接下來準備好在Flutter源碼世界里翱翔吧,以下分析基于v1.22.5分支的源碼。

俗話說,工欲善其事必先利其器,在源碼翱翔久了,容易迷茫,找不到東西南北,看到關(guān)鍵方法,又不知道是不是代碼真實的case,需要能驗證我們的想法,最簡單的辦法打斷點,有針對性的去看源碼。

3.1 IDE斷點

Flutter源碼的下載也很簡單,這里就不贅述了,大家可以上網(wǎng)搜下。Flutter工具鏈的源碼位于packages/flutter_tools下。

本文是通過Android Studio(比較熟)來配置和查看源碼,配置如下:

  • 第一步,先新建一個運行配置,選Dart Command Line App;
  • 第二步,找到Flutter源碼中工具鏈的入口文件,flutter_tools.dart;
  • 第三步,輸入想運行的命令;
  • 第四步,找到要調(diào)試的Flutter工程;

一頓配置下來,就可以用工具鏈完美的debug指定Flutter工程的源碼,接下來就是選好設(shè)備,點擊debug按鈕,如下圖:

3.2 整體流程

以下是Flutter熱重載流程圖:

簡述為:

  • 代碼改動:工具會掃描工程下的文件,通過修改時間來比對哪些文件被修改;
  • 首次編譯:第一次啟動會生成全量app.dill文件;
  • 增量編譯:對修改的文件編譯生成app.dill.incremental.dill增量文件;
  • 更新文件:將增量產(chǎn)物推送到設(shè)備中;
  • UI更新:DartVM收到增量文件后進行合并,并通知Flutter引擎更新UI

整個過程并沒有讓App重啟,從而達到高效開發(fā)調(diào)試效果。

3.3 源碼分析

3.3.1 run命令流程

我們從flutter run命令為入口分析,類位于packages/flutter_tools/lib/executable.dart中的main()方法,run命令最終實現(xiàn)類位于packages/flutter_tools/lib/src/commands/run.dart。

RunCommand在構(gòu)造函數(shù)中默認開啟了hot標識,如果需要關(guān)閉,要新增入?yún)?-no-hot。

從run命令的流程,可以看出,主要是做了默認參數(shù)設(shè)置,參數(shù)校驗,flutter設(shè)備初始,模式判斷等,熱重載是從HotRunner.run中開始執(zhí)行。

3.3.2 熱重載流程-首次啟動

在HotRunner中,流程也并不復(fù)雜:

可以看出,HotRunner做了三件事:

  • 對目標設(shè)備,編譯生成dill文件(有人叫kernel文件,本質(zhì)是一種中間描述,后文會介紹);
  • 對目標設(shè)備,安裝運行App;
  • 對目標設(shè)備進行attach,從而開啟attach;

第二步會涉及到不同平臺不同做法,對iOS和Android來說,分別對應(yīng)xcrun和adb,不是本文重點,流程也比較長,以后有機會再展開講,重點說第一步和第三步。

編譯生成dill文件

最終調(diào)用到_compile方法,代碼太過于繁瑣,我們直接斷點看,如下:

從斷點信息可以獲知,dart文件會被轉(zhuǎn)為kernel文件app.dill,以下截取部分app.dill內(nèi)容,可以看出app.dill是一份完整的代碼文件,包含了main.dart的內(nèi)容,右邊為main.dart源文件,左邊為app.dill文件內(nèi)容:

 

生成的app.dill是一份全量的代碼,接下來編譯不同設(shè)備(Android、iOS)的安裝包,同時運行指定的包。

此時生成app.dill的進程,我們暫且稱為“編譯進程”,后續(xù)熱重載增量的dill,也是驅(qū)動該進程生成。

attach設(shè)備

在上述的第二步,設(shè)備在啟動運行App時,會打開App中DartVM的Observatory服務(wù),本質(zhì)是一個websocket服務(wù),按照自定義的jsonrpc2.0協(xié)議進行通信,在attach時,會通過URI連接上設(shè)備服務(wù),如下圖:

連上DartVM服務(wù)后,會注冊幾個熱重載事件:reloadSources,reloadMethod,hotRestart,這幾個事件并不是注冊到App中的Dart虛擬機,而是提供給flutter tool其他命令使用,如下圖:

同時通過DartVM服務(wù),來初始設(shè)備中flutter產(chǎn)物,設(shè)備中產(chǎn)物路徑是臨時生成,用XXX代替,產(chǎn)物路徑為:

  • Android中為:file:///data/user/0/com.example.flutter_app/code_cache/XXX/flutter_app/
  • iOS模擬器中為:/Users/hexianting/資源庫/Developer/CoreSimulator/Devices/BC003085-8F19-4EF3-AB84-BD44282F79B7(模擬器設(shè)備ID)/data/Containers/Data/Application/745DE582-59F1-4193-9692-131E611A9359/tmp/XXX/flutter_app/

具體代碼如下:

3.3.3 觸發(fā)熱重載

下面分別從源碼角度,看看到底做了什么?

開發(fā)者在執(zhí)行flutter run或者flutter attach后,在終端中輸入r,即可體驗到重載效果,如果在Android Studio和VSCode中,直接Ctrl+S或者Cmd+S即可。

對應(yīng)到源碼入口:

不管是HotReload還是HotRestart,最終都是調(diào)用HotRunner.restart方法,一路跟進,最終會到某個具體設(shè)備update方法,并再次調(diào)用上述《熱重載流程-首次啟動》中的_compile方法,通知編譯進程生成增量的dill文件app.dill.incremental.dill。那這個增量文件到底是什么呢?demo中修改字符串"Flutter Demo Home Page"為"Flutter Demo Home Page2",來看看dill文件內(nèi)容:

第一張圖為修改前,第二種為修改后,第三張為增量的dill內(nèi)容。可以看出增量的dill文件僅包含改動的dart文件代碼。

生成增量的dill后,會通過_DevFSHttpWriter寫入設(shè)備,如下圖:

當同步完增量文件,最后還需要通知DartVM去刷新UI界面,這個步驟就跟我們上述的2.4節(jié)內(nèi)容類似:

vmService.reloadSources最終調(diào)用了_call方法,這是一個dart官方庫,如下:

HotRestart與HotReload區(qū)別

Flutter官方提供兩種快速調(diào)試方法,一種是HotReload,另一種是HotRestart。前者無感知局部刷新,體驗最好,但是缺點也很明顯,適用比較局限,可以參考官網(wǎng)給出樣例:HotReload,主要有這幾種場景不適用:

  • enum改成class類;
  • 字體修改;
  • 泛類型修改;
  • Android和iOS原生修改;

而在HotRestart流程中,相比HotReload流程,增加了清除資源操作,同時不再生成增量的dill文件,每次改動都是生成全量的app.dill文件,該細節(jié)就不展開,感興趣讀者可以debug源碼看。

上述可以看出HotRestart額外處理了一些事情,包括殺掉非UI的isolate,重置UI的isolate等。

對于dill文件同步到設(shè)備中位置,不同設(shè)備不一樣:

  • Android:file:///data/user/0/com.example.flutter_app/code_cache/XXX/flutter_app/lib/
  • iOS模擬器:/Users/hexianting/Library/Developer/CoreSimulator/Devices/BC003085-8F19-4EF3-AB84-BD44282F79B7(模擬器設(shè)備ID)/data/Containers/Data/Application/9C8E4694-AC99-4A5C-BC46-63567F1C6FD9/tmp/XXX/flutter_app/lib/

至此,熱重載源碼就告一段落,很多奇技淫巧并不能一一展現(xiàn),值得大家動手去看看。

四、總結(jié)

經(jīng)過上述一頓探索,文章最早提出的幾個疑問,想必都有了答案。這里只是介紹了Flutter源碼的冰山一角,更多源碼還需要繼續(xù)探索,通過閱讀源碼,可做的事情很多:

  • 通過文件監(jiān)聽+vm_service通信,干掉手動輸入r或者R的這種無(gou)語(shi)設(shè)計;
  • 源碼中并沒有限制多個設(shè)備,flutter run同時運行在多個模擬器中,并開啟熱重載;
  • iOS模擬器不重新安裝App的情況下,直接替換模擬器中的flutter產(chǎn)物,以達到快速調(diào)試手段;
  • debug狀態(tài)下的DartVM可以通過熱重載來動態(tài)化,但性能較低,與谷歌Flutter的高性能目標不符;

總之,可做的事情很多,那我們看源碼的意義就非常清晰:

  • 深入了解Flutter運行機制,去定制Flutter框架;
  • 通過研究這些頂級工程師的實現(xiàn)思路,去完善我們自己的邏輯體系,從而成為一個更加嚴謹?shù)娜恕?/li>

五、參考資料

  • https://flutter.dev/docs/development/tools/hot-reload
  • http://gityuan.com/2019/09/07/flutter_run/
  • https://github.com/dart-lang/sdk/blob/master/runtime/vm/service/service.md
  • http://static.kancloud.cn/alex_wsc/flutter_demo/1570089

 

責任編輯:未麗燕 來源: 京東零售云
相關(guān)推薦

2021-09-17 18:40:55

京東mPaaS移動端

2024-07-11 08:09:21

2019-03-21 19:19:35

新零售阿里云零售云

2021-09-16 18:44:05

京東云PaaS平臺Android

2018-01-22 10:33:01

云計算 新零售

2021-11-04 08:00:00

人工智能機器學習技術(shù)

2016-10-19 18:31:13

云存儲

2023-03-30 10:06:58

2023-05-11 08:00:30

2021-09-08 18:12:57

京東零售云

2018-03-20 09:56:50

新零售

2017-09-30 10:00:41

2022-06-28 13:41:43

京東數(shù)據(jù)處理

2022-05-18 13:24:47

京東調(diào)優(yōu)實踐

2018-06-06 17:39:03

2020-06-07 10:07:04

機器人零售業(yè)人工智能

2021-08-13 11:38:51

京東零售云智能出行

2017-10-30 17:18:15

阿里云
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 91免费电影 | 天天操网 | 日本精品在线一区 | 精品国产99 | 国产日韩精品久久 | 色网站视频 | 在线观看中文字幕 | 久久国产精品72免费观看 | 91精品在线观看入口 | 日本色综合 | 久草新在线 | 欧美男人天堂 | 国产高清美女一级a毛片久久w | 欧美一区二区三区久久精品 | 国产99小视频 | 97国产超碰 | 中文精品视频 | 久久久综合 | 超碰人人人 | 中文字幕高清视频 | 天天夜夜人人 | 亚洲精品二区 | 在线视频a| 欧美福利精品 | 欧美一级三级 | 国产欧美在线观看 | 黄色毛片在线观看 | 在线视频亚洲 | 国产中文字幕在线 | 色男人的天堂 | 亚洲一区 中文字幕 | 美日韩免费 | 成人高清在线视频 | 色偷偷噜噜噜亚洲男人 | www午夜视频| 中文字幕在线中文 | 成人三级在线观看 | 欧美久久久 | 亚洲成人动漫在线观看 | 99视频免费播放 | 欧美视频成人 |