Flutter JSON动态组件渲染插件json_dynamic_widget_plugin_components的使用

Flutter JSON动态组件渲染插件json_dynamic_widget_plugin_components的使用

目录

在线示例

简介

此插件用于JSON Dynamic Widget,允许将一组JSON小部件组合成一个组件。

关于

依赖加载器

依赖项是由nameversion组成的组合。

加载器用于从不同源加载原始格式的组件。

每个加载器都需要实现load方法:

Future<String?> load(Dependency dependency, BuildContext context);

目前支持的加载器有:

  • AssetDependencyLoader:从资源加载依赖项。可以通过AssetPathResolver配置,指定如何根据依赖项解析路径。
  • MemoryDependencyLoader:从内存映射中加载依赖项。
  • CachedDependencyLoader:缓存子依赖项加载器的结果。
依赖版本解析器

依赖版本解析器允许定义自定义版本解析策略。例如,在缺少版本字符串时可以定义查找latest版本的逻辑。

每个加载器都需要实现resolve方法:

Future<String> resolve(String name, String? version, BuildContext context);

目前支持的版本解析器有:

  • RequiredDependencyVersionResolver:要求依赖项中包含版本字符串,否则抛出错误。
组件规范

组件规范定义了版本、名称以及输入和输出集合。其内容只是用于构建组件的一组小部件。

字段定义:

  • name - 组件名称
  • version - 组件版本
  • inputs - 输入变量及其默认值列表
  • outputs - 可以在组件外部使用的输出变量列表
  • content - 使用输入并生成输出变量的小部件组

示例:

name: centered_text
version: 1.0.0
inputs:
- name: text
  description: The text value
  defaultValue: ''
outputs: []
content:
  type: center
  listen:
  - text
  args:
    child:
      type: text
      args:
        text: "${'This text is centered:' + text ?? ''}"
组件值封装

每个组件都可以有自己的值。

为了避免名称冲突,每个组件都有自己的独立注册表。

每个组件允许定义自己的输入和输出:

  • inputs - 组件可用的输入变量,调用方不传递任何值则使用默认值。如果输入值使用variables,则每次更新都会传递给组件注册表。
  • outputs - 可以导出到调用者注册表的输出变量。调用方不传递任何值意味着特定变量不会导出到调用者注册表。

例如:

"type": "component",
"args": {
    "name": "header",
    "inputs": {
      "text": "Some text for the header"
    },
    "outputs": {
        "header_click_count" : "header1_click_count"
    }
}

使用插件

  1. 绑定插件。
import 'package:json_dynamic_widget/json_dynamic_widget.dart';
import 'package:json_dynamic_widget_plugin_components/json_dynamic_widget_plugin_components.dart';

void main() {
  // 确保Flutter的绑定已完成
  WidgetsFlutterBinding.ensureInitialized();

  // ...

  // 获取注册表的实例
  var registry = JsonWidgetRegistry.instance;

  // 将插件绑定到注册表。这是必要的,以便注册表能够找到插件提供的小部件
  JsonComponentsPluginRegistrar.registerDefaults(registry: registry).withLoader(
    CachedDependencyLoader(
      cachedLoader: AssetDependencyLoader(
        pathResolver: DirAssetPathResolver(
          basePath: 'assets/components', // {components_path}
          ext: Ext.json,
          extByDependencyName: {
            'centered_text': Ext.yaml,
          },
        ),
      ),
    ),
  );

  // ...
}
  1. 创建包含组件数据的JSON文件,并将其放置在{components_path}/{component_name}/{version}.json中。
// {components_path}/custom_text_input/1.0.0.json
{
    "name": "custom_text_input",
    "version": "1.0.0",
    "inputs": [
        {
            "name": "label",
            "description": "The text input label",
            "defaultValue": ""
        },
        {
            "name": "hint",
            "description": "The text input hint",
            "defaultValue": ""
        }
    ],
    "outputs": [
        {
            "name": "text_input",
            "description": "The text input value"
        }
    ],
    "content": {
        "type": "text_form_field",
        "id": "text_input",
        "args": {
            "decoration": {
                "hintText": "${hint}",
                "labelText": "${label}",
                "suffixIcon": {
                    "type": "icon_button",
                    "args": {
                        "icon": {
                            "type": "icon",
                            "args": {
                                "icon": {
                                    "codePoint": 57704,
                                    "fontFamily": "MaterialIcons",
                                    "size": 50
                                }
                            }
                        },
                        "onPressed": "${set_value('text_input','')}"
                    }
                }
            },
            "validators": [
                {
                    "type": "required"
                }
            ]
        }
    }
}
  1. json_dynamic_widget中使用组件。
"type": "component",
"args": {
    "name": "custom_text_input",
    "version": "1.0.0", 
    "inputs": {
        "label": "First name",
        "hind": "John"
    },
    "outputs": {
        "text_input": "first_name_input_value"
    }
}

示例代码

import 'dart:convert';

import 'package:json_dynamic_widget/json_dynamic_widget.dart';
import 'package:json_dynamic_widget_plugin_components/json_dynamic_widget_plugin_components.dart';
import 'package:logging/logging.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  Logger.root.onRecord.listen((record) {
    debugPrint('${record.level.name}: ${record.time}: ${record.message}');
    if (record.error != null) {
      debugPrint('${record.error}');
    }
    if (record.stackTrace != null) {
      debugPrint('${record.stackTrace}');
    }
  });

  final navigatorKey = GlobalKey<NavigatorState>();

  final registry = JsonWidgetRegistry.instance;
  JsonComponentsPluginRegistrar.registerDefaults(registry: registry).withLoader(
    CachedDependencyLoader(
      cachedLoader: AssetDependencyLoader(
        pathResolver: DirAssetPathResolver(
          basePath: 'assets/components',
          ext: Ext.json,
          extByDependencyName: {
            'centered_text': Ext.yaml,
          },
        ),
      ),
    ),
  );

  registry.navigatorKey = navigatorKey;

  final data = JsonWidgetData.fromDynamic(
    json.decode(await rootBundle.loadString('assets/pages/components.json')),
    registry: registry,
  );

  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      home: ComponentWidgetPage(
        data: data,
      ),
      theme: ThemeData.light(),
    ),
  );
}

class ComponentWidgetPage extends StatelessWidget {
  const ComponentWidgetPage({
    super.key,
    required this.data,
  });
  final JsonWidgetData data;

  [@override](/user/override)
  Widget build(BuildContext context) => data.build(context: context);
}

更多关于Flutter JSON动态组件渲染插件json_dynamic_widget_plugin_components的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter JSON动态组件渲染插件json_dynamic_widget_plugin_components的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用 json_dynamic_widget_plugin_components 插件在 Flutter 中进行 JSON 动态组件渲染的示例代码。这个插件允许你根据 JSON 数据动态生成 Flutter 组件。

首先,确保你已经在 pubspec.yaml 文件中添加了依赖:

dependencies:
  flutter:
    sdk: flutter
  json_annotation: ^4.3.0
  json_dynamic_widget: ^4.0.0
  json_dynamic_widget_plugin_components: ^4.0.0

然后,运行 flutter pub get 来安装依赖。

接下来是一个完整的示例,展示如何使用 json_dynamic_widget_plugin_components 插件:

import 'package:flutter/material.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:json_dynamic_widget/json_dynamic_widget.dart';
import 'package:json_dynamic_widget_plugin_components/json_dynamic_widget_plugin_components.dart';

// 示例 JSON 数据
final String jsonData = '''
{
  "type": "Column",
  "children": [
    {
      "type": "Text",
      "text": "Hello, World!"
    },
    {
      "type": "ElevatedButton",
      "child": {
        "type": "Text",
        "text": "Click Me"
      },
      "onPressed": {
        "type": "Function",
        "function": "onButtonPressed"
      }
    }
  ]
}
''';

// 定义一个函数来模拟按钮点击事件
void onButtonPressed() {
  print("Button was pressed!");
}

// 注册自定义函数
void registerCustomFunctions(JsonWidgetRegistry registry) {
  registry.registerFunction('onButtonPressed', () => onButtonPressed());
}

void main() {
  // 注册自定义组件和函数
  JsonWidgetData jsonWidgetData = JsonWidgetData.withData(
    jsonData,
    plugins: [
      JsonDynamicWidgetPluginComponents(),
    ],
    registry: JsonWidgetRegistry.instance..register(registerCustomFunctions),
  );

  runApp(MaterialApp(
    home: Scaffold(
      appBar: AppBar(
        title: Text('JSON Dynamic Widget Example'),
      ),
      body: JsonDynamicBuilder.buildFromData(
        jsonWidgetData,
      ),
    ),
  ));
}

代码说明:

  1. 依赖导入

    • 导入必要的 Flutter 和 JSON 动态组件渲染插件包。
  2. 示例 JSON 数据

    • 定义一个 JSON 字符串,表示一个 Column 组件,包含两个子组件:一个 Text 组件和一个 ElevatedButton 组件。按钮的 onPressed 属性绑定了一个自定义函数 onButtonPressed
  3. 自定义函数

    • 定义一个 onButtonPressed 函数,用于模拟按钮点击事件。
  4. 注册自定义函数

    • 使用 JsonWidgetRegistry 注册自定义函数,使得 JSON 数据中的函数引用可以被正确解析和调用。
  5. JSON 数据解析和渲染

    • 使用 JsonWidgetData.withData 方法将 JSON 数据、插件列表和注册信息封装成一个 JsonWidgetData 对象。
    • 使用 JsonDynamicBuilder.buildFromData 方法将 JsonWidgetData 对象渲染为 Flutter 组件。
  6. 运行应用

    • main 函数中,使用 MaterialAppScaffold 创建一个简单的 Flutter 应用,并将解析后的 JSON 数据作为应用的内容。

这个示例展示了如何使用 json_dynamic_widget_plugin_components 插件根据 JSON 数据动态生成 Flutter 组件,并处理 JSON 数据中的自定义函数引用。你可以根据需要扩展这个示例,添加更多的组件和自定义函数。

回到顶部