fair 的一些配置

150 阅读1分钟

自己的烂笔头 他人看不懂 莫看

main 入口

runApp(const MyApp());

修改为

FairApp.runApplication(
    FairApp(
      // generated: g.AppGeneratedModule(),
      generated: AppGeneratedModule(),
      delegate: <String, FairDelegateBuilder>{
        'TestPage': (context, data) => TestPageFairDelegate(),
        'HotUpdateIssue': (context, data) => HotUpdateIssueDelegate(),
        'HotUpdate': (context, data) => HotUpdateDelegate(),
      },
      dynamicWidgetBuilder: [
        (proxyMirror, page, bound, {bundle}) => CustomDynamicWidgetBuilder(proxyMirror, page, bound, bundle: bundle)
      ],
      child: MyApp(),
        // httpDecoder:DefaultHttpDecoder(),
    ),
    plugins: <String, IFairPlugin>{'FairCommonPlugin': FairCommonPlugin()});

自定义的js解析器

///生成项目组件的映射 g.AppGeneratedModule()


@FairBinding(packages: [
  'package:cses_saas/widgets/button/radius_inkwell_widget.dart',
  'package:cses_saas/modules/mutualism/task/create_task/widget/item_priority.dart',

])
void main() async {
  FairJSDecoder.resolve = (String? jsPath) async {
    return CustomFairJSDecoder().decode(jsPath);
  };
}

自定义的解析器 json 和 js 和

import 'dart:convert';

import 'package:cses_saas/cses_saas.dart';
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:dio/dio.dart';
import 'dart:io';
import 'package:fair/src/internal/bundle_provider.dart';
import 'package:flutter/services.dart';
import 'package:flutter/foundation.dart';
import 'package:fair/src/internal/fair_decoder.dart';

///自定义的解析json
class CustomDynamicWidgetBuilder extends DynamicWidgetBuilder {
  CustomDynamicWidgetBuilder(
    super.proxyMirror,
    super.page,
    super.bound, {
    super.bundle,
  });

  @override
  dynamic convert(BuildContext context, Map map, Map? methodMap, {Domain? domain}) {
    var name = map[tag];

    ///tag的本质是传入的className
    if (name == "data") {
      print("=====================api${map}========================");
      return;
    }
    if (name == "Tab") {
      print("=====================api${Tab}========================");
      return;
    }
    print(
        "解析的    methodMap$methodMap =========map$map========== ${name}=========================== ${domain}===================");

    return super.convert(context, map, methodMap, domain: domain);
  }
}

Map<String?, String> _cache = <String?, String>{};
Map<String?, Map?> _cacheJson = <String?, Map?>{};

/// 自定义 js 获取方式
class CustomFairJSDecoder with FairBundlePathCheck {
  factory CustomFairJSDecoder() => _customFairJSDecoder;

  CustomFairJSDecoder._();

  static final CustomFairJSDecoder _customFairJSDecoder = CustomFairJSDecoder._();

  static const BYTES_LIMIT = 10 * 1024;
  static const STRING_LIMIT = 10 * 1024 / 8;

  Future<String> _decode(String? url) async {
    var start = DateTime.now().millisecondsSinceEpoch;
    // var response = await HttpManager().get(Uri.parse(url??''));
    var response = await Dio().get(url ?? '');
    var end = DateTime.now().millisecondsSinceEpoch;
    print('end1 ${end - start}');
    if (response.statusCode != 200) {
      throw FlutterError('加载JS网络路径Code =${response.statusCode},RemoteUrl: $url');
    }
    var end2 = DateTime.now().millisecondsSinceEpoch;
    print('end ${end2 - start}');
    var data = response.data;
    if (data == null) {
      throw FlutterError('bodyBytes=null, RemoteUrl : $url');
    }
    //解析字节流
    return _resolveResult(data);
  }

  Future<String> _resolveResult(dynamic data) async {
    String result;
    if (data is Uint8List) {
      if (data.lengthInBytes < BYTES_LIMIT) {
        result = utf8.decode(data);
      } else {
        result = await compute(_toString, data, debugLabel: 'json decode');
      }
    } else {
      result = data as String;
    }
    return result;
  }

  String _toString(Uint8List data) {
    return utf8.decode(data);
  }

  Future<String> _resolveAssert(String? assertPath) async {
    if (isExternalStoragePath(assertPath)) {
      var file = File(assertPath ?? '');
      return await file.readAsString();
    }
    return rootBundle.loadString(assertPath ?? '');
  }

  Future<String> _resolve(String? path) async {
    if (path?.startsWith('http') == true) {
      return await _decode(path);
    } else {
      //10kb以上资源,会通过isolate的方式去实现,无需额外去操作
      //10KB takes about 3ms to parse on a Pixel 2 XL.
      return _resolveAssert(path);
    }
  }

  Future<String> decode(String? jsPath) => _resolve(jsPath);
}

//自定义的资源加载
class CustomFairBundleLoader extends FairBundleProvider {
  @override
  Future<Map?> onLoad(
    String? path,
    FairDecoder decoder, {
    bool cache = true,
    Map<String, String>? h,
  }) async {
    //
    // var byteData = null;
    // if (byteData != null) {
    //   //
    // }
    // else
    // {
    // 根据自身的情况来,这个也可能从其他地方获取
    // 缓存的是 path 对应的 map
    return _cacheJson[path] ??= await super.onLoad(
      path,
      decoder,
      cache: cache,
      h: h,
    );
  }
//}
}

//}

插件部分

assest 下添加 fair_basic_config.json 名字不可改

image.png

{
"plugin": {
"fair_common_plugin": "assets/plugin/fair_common_plugin.js"
}
}

在plugin下添加与js的插件

image.png

此部分与dart中一一对应

let FairCommonPlugin = function () {
    return {
        http: function (resp) {
            fairCommonPluginRequest(resp, 'http');
        },
       showMessageToast: function (resp) {
                   fairCommonPluginRequest(resp, 'showMessageToast');
              },
        remove: function (resp) {
                     fairCommonPluginRequest(resp, 'remove');
                            },
         getTitle: function (resp) {
                     fairCommonPluginRequest(resp, 'getTitle');
                          },
    }
}

dart 中

/// 跟 js 交互的方法类
class FairCommonPlugin extends IFairPlugin with HttpPlugin, ToastPlugin, BaseInfoPlugin {
  factory FairCommonPlugin() => _fairCommonPlugin;

  FairCommonPlugin._();

  static final FairCommonPlugin _fairCommonPlugin = FairCommonPlugin._();

  @override
  Map<String, Function> getRegisterMethods() {
    return <String, Function>{
      'showMessageToast': showMessageToast,
      'http': http,
      'remove': remove,
      'getTitle': getTitle,
    };
  }
}

mixin HttpPlugin implements FairCommonPluginMixin {
  Future<dynamic> http(dynamic map) => request(
        map,
        (dynamic requestMap) async {
          final method = requestMap['method'];
          final url = requestMap['url'];
          final headers = requestMap['headers'];
          final body = requestMap['body'];
          Map<String, dynamic>? params = {};
          params.addAll(headers);
          params.addAll(body);
          switch (method) {
            case 'POST':
              final Response result = await HttpManager().post(
                url,
                params: params,
              ) as Response;
              return {
                'json': jsonDecode(result.body),
                'statusCode': result.statusCode,
              };
            default:
          }
          print("调用了http方法");

          return null;
        },
      );
}

mixin ToastPlugin implements FairCommonPluginMixin {
  Future<dynamic> showMessageToast(dynamic map) => request(
        map,
        (dynamic requestMap) async {
          final msg = requestMap['msg'];
          showToast(text: msg);
          return null;
        },
      );
}

mixin BaseInfoPlugin implements FairCommonPluginMixin {
  Future<dynamic> remove(dynamic map) => request(
        map,
        (dynamic requestMap) async {
          var index = requestMap['index'];
          Get.find<CreateTaskLogic>(tag: TaskType.issue.toString()).removeIssueTasks(index);
          return null;
        },
      );

  Future<dynamic> getTitle(dynamic map) async {
    print(map);
    Map params = json.decode(map);
    Map<String, dynamic> request = params["request"] ?? {};
    var index = request['index'] ?? 0;
    final String title = Get.find<CreateTaskLogic>(tag: TaskType.issue.toString()).issueTasks[index].title ?? "";
    var resp = {"title": title};

    print("title$title ======================================");
    return Future.value(jsonEncode(resp));
  }
}

逻辑层的写法与绑定

class HotUpdateDelegate extends FairDelegate {
  CreateTaskLogic get logic => Get.find<CreateTaskLogic>(tag: TaskType.issue.toString());
  late ScrollPhysics scrollPhysics;

  @override
  void initState() {
    super.initState();
    onLoad();
  }

  void onLoad() {
    scrollPhysics = const NeverScrollableScrollPhysics();
  }

  @override
  Map<String, PropertyValue> bindValue() {
    return {
      ...super.bindValue(),
      // key 跟页面上面的名字一致
      "scrollPhysics": () => scrollPhysics,
      'logic': () => logic,
      'taskType': () => TaskType.issue,
      'showLinkTask': () => logic.issueTasks.isNotEmpty
    };
  }

  @override
  Map<String, Function> bindFunction() {
    return {
      ...super.bindFunction(),
      'createIssueTask': createIssueTask,
      'onTapLinkTask': onTapLinkTask,
      'issueTaskCount': issueTaskCount,
      'priorityText': priorityText,
    };
  }

  void onTapLinkTask() async {
    FocusScope.of(context).requestFocus(FocusNode());
    Get.bottomSheet(const IssueTasksDialog(),
            clipBehavior: Clip.antiAlias,
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.only(topLeft: Radius.circular(20.r), topRight: Radius.circular(20.r))))
        .then((value) {
      if (value != null) logic.addAssociationIssue(value);
      setState(() {});
    });
  }

  int issueTaskCount() {
    return logic.issueTasks.length;
  }

  void createIssueTask() {
    logic.createIssueTask();
  }




  String priorityText(index) {
    return logic.issueTasks[index].priorityText ?? '';
  }

  Color priorityColor(index) {
    return logic.issueTasks[index].priorityColor;
  }
}

image.png