精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Flutter如何將代碼顯示到界面上呢?

OSC開源社區 ? 來源:OSCHINA 社區 ? 2023-05-10 10:04 ? 次閱讀

前言

如何優雅的將項目中的代碼,亦或是你的 demo 代碼展示到界面上?本文對使用簡單、便于維護且通用的解決方案,進行相關的對比和探究

為了節省大家的時間,把最終解決方案的相關接入和用法寫在前面

預覽代碼

快速開始

接入:pub,github

dependencies:
  code_preview: ^0.1.5

用法:CodePreview,提供需要預覽的 className,可自動匹配該類對應的代碼文件

本來想把寫法簡化成傳入對象,但是因為一些原因無奈放棄,改成了className

具體可以參考下面Flutter Web中的問題模塊的說明

import 'package:code_preview/code_preview.dart';
import 'package:flutter/material.dart';

class Test extends StatelessWidget {
  const Test({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const CodePreview(className: 'Test');
  }
}

使用效果:flutter_smart_dialog

06191504-ee71-11ed-90ce-dac502259ad0.png

配置代碼文件

因為原理是遍歷資源文件,所以必須將需要展示的代碼文件或者其文件夾路徑,定義在 assets 下,這步操作,為大家提供了一個自動化的插件解決

強烈建議需要展示到界面的代碼,都放在統一的文件夾里管理

展示界面的代碼需要在 pugspec.yaml 中的 assets 定義

063e2df8-ee71-11ed-90ce-dac502259ad0.png

如果代碼預覽的文件夾,分級復雜,每次都需要定義路徑實在麻煩

提供一個插件:Flutter Code Helper

安裝:Plugins 中搜索Flutter Code Helper

066af856-ee71-11ed-90ce-dac502259ad0.png

pugspec.yaml 中定義下需要自動生成文件夾的路徑,文件夾隨便套娃,會自動幫你遞歸在 assets 下生成

不需要自動生成,可:不寫該配置,或者配置空數組(auto_folder: [])

code_helper:
  auto_folder: [ "assets/", "lib/widgets/" ]

說明下:上面的插件是基于 RayC 的 FlutterAssetsGenerator 插件項目改的

看了下 RayC 的插件代碼和相關功能,和我預想的上面功能實現有一定出入,改動起來變動較大

想試下插件項目的各種新配置,直接拉到最新

后期如果想到需要什么功能,方便隨時添加

所以沒向其插件里面提 pr,就單獨新開了個插件項目

高級使用

主題

提供倆種代碼樣式主題

日間模式

CodePreview.config = CodePreviewConfig(codeTheme: CodeTheme.light);

06816ae6-ee71-11ed-90ce-dac502259ad0.png

夜間模式

CodePreview.config = CodePreviewConfig(codeTheme: CodeTheme.dark);

06a70c42-ee71-11ed-90ce-dac502259ad0.png

注釋解析

你可以使用如下的格式,在類上添加注釋

key 的前面必須加@,舉例(@title,@xxx)

key 與 value 的之間,必須使用分號分割,舉例(@xxx: xxx)

value 如果需要換行,換行的文案前必須加中劃線

/// @title:
///  - test title one
///  - test title two
/// @content: test content
/// @description: test description
class OneWidget extends StatelessWidget {
  const OneWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}

然后可以從customBuilder的回調獲取 param 參數,param 中擁有 parseParam 參數

獲取取得上面注釋的數據:param.parseParam ['title'] 或者 param.parseParam ['***']

獲取的 value 的類型是 List,可兼容多行 value 的類型

customBuilder的用法

codeWidget內置的代碼預覽布局,如果你想定義自己預覽代碼的布局,那就可以不使用codeWidget

一般來說,可以根據注釋獲取的數據,結合codeWidget嵌套來自定義符合要求的布局

param中含有多個有用內容,可自行查看

import 'package:code_preview/code_preview.dart';
import 'package:flutter/material.dart';

class Test extends StatelessWidget {
  const Test({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CodePreview(
      className: 'OneWidget',
      customBuilder: (Widget codeWidget, CustomParam? param) {
        debugPrint(param?.parseParam['title'].toString());
        debugPrint(param?.parseParam['content'].toString());
        debugPrint(param?.parseParam['description'].toString());
        return codeWidget;
      },
    );
  }
}

目前內部預覽的布局,會自動去掉類上的注釋,如果想保留注釋,可自行匹配下

 CodePreview.config = CodePreviewConfig(removeParseComment: false);

幾種代碼預覽方案

FlutterUnit 方案

FlutterUnit 項目也是自帶代碼預覽方案,這套方案是比較特殊方案

大概看了下,整個 FlutterUnit 的數據都是基于flutter.db,該文件里面就有相關 demo 的文本信息

所有的 demo 也是單獨存在一個叫widgets的項目中

所以大概可以猜測出

應該會有個 db 的輔助工具,會去掃描widgets的項目中的 demo 代碼

將他們的文本信息都掃描出來,然后解析上面的注釋等相關信息,分類存儲到數據庫中,最后生成 db 文件

06bf34fc-ee71-11ed-90ce-dac502259ad0.png

映射表,宿主可以通過 db 中的組件類名,從這里拿到 demo 效果實例

0700048c-ee71-11ed-90ce-dac502259ad0.png

總結

整套流程看下來,實現起來的工作量還是有點大的

db 輔助工具的編寫

文本注釋相關解析規則

如何便捷的維護 db 文件(輔助工具是否支持,生成后自動覆蓋宿主 db 文件)

不同平臺 db 文件的讀取和相關適配

優點

因為掃描工具不依賴 Flutter 相關庫,預覽方案可以快速的移植到其它編程語言(compose,SwiftUI 等)

具備高度自定義,因為是完全獨立的第三方掃描工具,可以隨性所欲的定制化

缺點

最明顯的缺點,應該就是稍微改下 demo 代碼,就需要三方工具重新生成 db 文件(如果三方工具實現的是 cli 工具,可以將掃描生成命令和 push 等命令集成一起,應該可以比較好的避免該問題)

build_runner 方案

build_runner 是個強大代碼自動生成工具,根據 ast 語法樹 + 自定義注解信息,可以生成很多強大的附屬代碼信息,例如json_serializable等庫

所以,也能利用這點自定義類注解,獲取到對應的整個類的代碼信息,在對應附屬的xx.g.dart文件中,將獲取的代碼內容轉換成字符串,然后直接將xx.g.dart文件的代碼字符串信息,展示到界面就行了

優點

可以通過生成命令,全自動的生成代碼,甚至將整個預覽 demo 的映射表都可以自動配置完成

可以規范的通過注解配置多個參數

缺點

因為build_runner需要解析整個 ast 語法樹,一旦項目很大之后,解析生成的時間會非常非常的長!

因為現在很多的這類庫都是依賴build_runner,所以跑自動生成命令,會導致巨多xx.g.dart文件被改動,極大的增加 cr 工作量

資源文件方案

這應該最常用的一種方案

在pubspec.yaml中的assets中定義下我們代碼文件路徑

flutter:
  assets:
    - lib/widgets/show/

然后用 loadString 獲取文件內容

final code = await rootBundle.loadString('lib/widgets/show/custome_dialog_animation.dart');

072a8b8a-ee71-11ed-90ce-dac502259ad0.png

優點

侵入性非常低,不會像build_runnner方案那樣影響到其它模塊

便于維護,如果 demo 預覽代碼被改變了,打包的時候,資源文件也會生成對應改變后的代碼文件

缺點

使用麻煩,使用的時候需要傳入具體的文件路徑,才能找到想要的代碼資源文件

需要反復的在pubspec.yaml中的assets里面定義文件路徑

資源文件方案優化

上面的三種方案各有優缺點,明確當前的訴求

目前是想寫個簡單的,通用的,僅在 Flutter 中實現代碼預覽方案

要求使用簡單,高效

維護簡單,多人開發的時候不會有很大成本

FlutterUnit 方案:實現起來成本較大,且多人開發對單個 db 文件的維護很可能會有點問題,例如:更新代碼的時候,db 文件忘記更新

build_runner 方案:生成時間是個問題,還有很對其他類型xx.g.dart文件產生影響也比較麻煩

資源文件方案:整體是符合預期的,但是使用時候,需要傳入路徑和pubspec.yaml中反復定義文件路徑,這是倆個很大痛點

結合實現成本和訴求,選擇資源文件方案,下面對其痛點進行優化

使用優化

Flutter 的編譯產物中,有個相當有用的文件:AssetManifest.json

AssetManifest.json 文件里面,有所有的資源文件的路徑,然后就簡單了,我們只需要讀取該文件內容

final manifestContent = await rootBundle.loadString('AssetManifest.json');

獲取到所有的路徑之后,再結合傳入的類名,讀取所有路徑的文件內容,然后和傳入的類名做正則匹配就行了

稍微優化

將傳入的類名,轉換為下劃線名稱和所有路徑名稱做匹配,如果能匹配上,再進行內容匹配,匹配成功后就返回該文件的代碼內容

如果上述匹配失敗,就進行兜底的全量匹配

優化前

import 'package:code_preview/code_preview.dart';
import 'package:flutter/material.dart';

class Test extends StatelessWidget {
  const Test({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const CodePreview(path: 'lib/widgets/show/custome_dialog_animation.dart');
  }
}

優化后

import 'package:code_preview/code_preview.dart';
import 'package:flutter/material.dart';

class Test extends StatelessWidget {
  const Test({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const CodePreview(className: 'CustomDialogAnimation');
  }
}

一般來說,我是統一配置預覽 demo 和 className,這樣比較好對照

07509834-ee71-11ed-90ce-dac502259ad0.png

路徑定義優化

本來是想在pubspec.yaml的assets里面直接寫通配符定義全路徑,然后悲劇了,它不支持這種寫法

flutter:
  assets:
    - lib/widgets/**/*.dart

GG,只能想其他辦法了,想了很多方法都不行,只能從外部入手,用 idea 插件的形式,實現自動化掃描生成路徑

安裝:Plugins 中搜索Flutter Code Helper

066af856-ee71-11ed-90ce-dac502259ad0.png

pugspec.yaml 中定義下需要自動生成文件夾的目錄,文件夾隨便套娃,會自動幫你遞歸在 assets 下生成

不需要自動生成,可:不寫該配置,或者配置空數組(auto_folder: [])

code_helper:
  auto_folder: [ "assets/", "lib/widgets/" ]

Flutter Web 中的問題

魔幻的 runtimeType

flutter web 的 release 模式中

dart2js 會壓縮 JS,這樣會使得類型名被改變

例如:dart 中的TestWidgetFunction類的 runtimeType,可能會變成minified:Ah,而不是TestWidgetFunction!

為啥需要壓縮呢?壓縮名稱可以使得編譯器將 JavaScript 體積縮小 3 倍 +;精確等效語義和性能 / 代碼大小之間的權衡,Dart 明顯是選擇了后者

這種情況只會在 Flutter Web 的 release 模式下發生,其他平臺和 Flutter web 的 Debug | Profile 模式都不會有這種問題;所以說Xxx.runtimeType.toString,并不一定會得到預期內的數據。。。

解決思路

將壓縮類型minified:Ah恢復成Test

將獲取的Test字符串使用相同算法壓縮成minified:Ah

如有知道如何實現的,務必告訴鄙人

下面從壓縮級別調整的角度,探究是否可解決該問題

dart2js 壓縮說明

注:flutter build web 默認的是 O4 優化級別

O0: 禁用許多優化。

O1: 啟用默認優化 (僅是 dart2js 該命令的默認級別)

O2: 在 O1 優化基礎上,尊重語言語義且對所有程序安全的其他優化(例如縮小)

備注:使用 - O2, 使用開發 JavaScript 編譯器編譯時,類型的字符串表示不再與 Dart VM 中的字符串表示相同

O3: 在 O2 優化基礎上,并省略隱式類型檢查。

注意:省略類型檢查可能會導致應用程序因類型錯誤而崩潰

O4: 在 O3 優化基礎上,啟用更積極的優化

注意:O4 優化容易受到輸入數據變化的影響,在依賴 O4 之前,需測試用戶輸入中的邊緣情況

下面是 flutter 新建項目,未做任何改動,不同壓縮級別的 js 產物體積

# main.dart.js: 7.379MB
flutter build web --dart2js-optimization O0 
# main.dart.js: 5.073MB
flutter build web --dart2js-optimization O1
# main.dart.js: 1.776MB
flutter build web --dart2js-optimization O2
# main.dart.js: 1.716MB
flutter build web --dart2js-optimization O3
# main.dart.js: 1.687MB
flutter build web --dart2js-optimization O4

總結

預期用法

為什么想使用對象?因為當對象名稱改變時,對應使用的地方,可以便捷觀察到需要改變

可以使用傳入的對象實例,在內部使用 runtimeType 獲取類型名,再進行相關匹配

CodePreview(code: Test());

但是

綜上可知,使用flutter build web --dart2js-optimization O1編譯的 flutter web release 產物,能夠使得 runtimeType 的語義和 Dart VM 中字符串保持一致

但是該壓縮級別下的,js 體積過于夸張,務必會對加載速度產生極大影響,可想而知,在復雜項目中的體積增漲肯定更加離譜

對于想要用法更加簡單,使用低級別壓縮命令打包的想法需要舍棄

用法不得已做妥協

CodePreview(className: "Test");

這是個讓我非常糾結的思路歷程

最后

到這里也結束了,自我感覺,對大家應該能有一些幫助

一般來說,大部分團隊,都會有個自己的內部組件庫,因為 Flutter 強大的跨平臺特性,所以就能很輕松的發布到 web 平臺,可以方便的體驗各種組件的效果,結合文章中的代碼預覽方案,就可以更加快速的上手各種組件用法了~





審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Rayc
    +關注

    關注

    0

    文章

    2

    瀏覽量

    6014
  • flutter
    +關注

    關注

    0

    文章

    13

    瀏覽量

    437

原文標題:Flutter如何將代碼顯示到界面上

文章出處:【微信號:OSC開源社區,微信公眾號:OSC開源社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    鴻蒙Flutter實戰:07混合開發

    # 鴻蒙Flutter實戰:混合開發 鴻蒙Flutter混合開發主要有兩種形式。 ## 1.基于har flutter module打包成har包,在原生鴻蒙項目中,以har包
    發表于 10-23 16:00

    鴻蒙Flutter實戰:08-如何調試代碼

    ,找到 Flutter Attach , Flutter 調試器連接至宿主機 然后就是增加斷點,使用hot reload 重新加載 Flutter,調試項目
    發表于 10-23 16:29

    鴻蒙Flutter實戰:11-使用 Flutter SDK 3.22.0

    # 使用 Flutter SDK 3.22.0 ## SDK 安裝 參考[鴻蒙Flutter實戰:01-搭建開發環境]文章的說明,首先安裝 Flutter SDK 3.22.0。 目前鴻蒙化
    發表于 11-01 15:03

    深入理解flutter的編譯原理與優化

    摘要: 閑魚技術-正物 問題背景 對于開發者而言,什么是Flutter?它是用什么語言編寫的,包含哪幾部分,是如何被編譯,運行設備上的Flutter如何做到Debug模式Hot
    發表于 07-02 17:47

    如何將代碼集成Multi IDE Project?

    我想知道是否可以使用PinMap向導生成C代碼以與Multi IDE Green Hill編譯器一起使用,如果可以的話,如何將代碼集成Multi IDE Project? 提前致
    發表于 06-21 10:05

    界面上顯示和輸入控件特別多時如何管理

    如果在一個界面上有幾十個控件(顯示和輸入都有),類型還不一樣,請問如何管理這些控件,現在我都是用很多事件結構來做的,請問大家有什么好的方法?特別是在ActorFramework框架中。
    發表于 09-09 19:32

    如何將現有代碼一點點移植HC32F460上

    如何將現有代碼一點點移植HC32F460上?其移植過程是怎樣的?
    發表于 11-25 06:27

    如何將STM32的代碼以日期作為軟件版本號去實現

    如何將STM32的代碼以日期作為軟件版本號去實現?求大神解答
    發表于 12-15 06:20

    如何將顯示緩沖區的數據取出拼裝成一個字節

    如何將顯示緩沖區的數據取出拼裝成一個字節?如何修改程序
    發表于 01-21 07:34

    如何將示例flutter應用程序安裝到STM32MP157F-DK2?

    /environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabiexport CC=${CLANGCC}export CXX=${CLANGCXX}我的問題是如何將一個簡單的 flutter 應用程序安裝到我的發現
    發表于 12-06 07:14

    如何將ST25dv sdk移植Flutter

    我想開發一個簡單的應用程序來讀/寫 ST25DV 設備的內部 EEPROM。是否有 ST25dv sdk Flutter 的移植?
    發表于 01-03 09:01

    如何將BLDC進電機控制算法移植STM微控制器上

    為 STSPIN 提供的 6 步算法。我們應該將該代碼移植到任何其他 ST 控制器嗎?如何將BLDC進電機控制算法移植STM微控制器上
    發表于 01-17 08:54

    如何將X-CUBE-NFC5代碼集成平臺中?

    ,我只是主要的 .c 和 .h 文件從 RFAL 和 BSP 文件夾復制項目中,但出現了很多錯誤。是否有關于如何將代碼添加到項目或我需要使用哪些軟件來使用 X-CUBE-NFC5
    發表于 02-02 07:22

    如何將JavaScript代碼嵌入HTML頁面

    本教程向您展示如何將JavaScript代碼嵌入HTML頁面,來幫助您開始學習 JavaScript。
    的頭像 發表于 12-14 17:46 ?1146次閱讀

    Flutter 共創未來 | Flutter Forward 活動精彩回顧

    Flutter Forward 活動 https://flutter.dev/events/flutter-forward Flutter 是一個
    的頭像 發表于 02-22 23:20 ?563次閱讀