【问题标题】:Unable to build Flutter Web and Flutter Mobile apps seperately无法分别构建 Flutter Web 和 Flutter Mobile 应用
【发布时间】:2020-06-08 17:47:30
【问题描述】:

我正在构建一个 Flutter 项目,但在将 Web 和移动代码集成到一个项目中时遇到了问题。我想在我的移动代码中使用 Moor 和 Moor_FFI,但是即使我的 web 入口点 (main.dart) 和移动代码 (main.dev.dart) 配置为与调试不同,它仍然会尝试编译用于网络的移动代码。这会导致一个问题,因为 Flutter Web 目前不支持 FFI 和其他 Dart 插件,从而导致大量错误消息。

Error compiling dartdevc module:ffi|lib/ffi.ddc.js

packages/ffi/src/utf8.dart:6:8: Error: Not found: 'dart:ffi'
import 'dart:ffi';
       ^
packages/ffi/src/utf16.dart:6:8: Error: Not found: 'dart:ffi'
import 'dart:ffi';
       ^
packages/ffi/src/allocation.dart:5:8: Error: Not found: 'dart:ffi'
import 'dart:ffi';
       ^
packages/ffi/src/utf8.dart:23:20: Error: Type 'Struct' not found.
class Utf8 extends Struct {
                   ^^^^^^
packages/ffi/src/utf8.dart:26:21: Error: Type 'Pointer' not found.
  static int strlen(Pointer<Utf8> string) {
                    ^^^^^^^
packages/ffi/src/utf8.dart:26:21: Error: Expected 0 type arguments.
  static int strlen(Pointer<Utf8> string) {
                    ^
packages/ffi/src/utf8.dart:41:26: Error: Type 'Pointer' not found.
  static String fromUtf8(Pointer<Utf8> string) {
                         ^^^^^^^
packages/ffi/src/utf8.dart:41:26: Error: Expected 0 type arguments.
  static String fromUtf8(Pointer<Utf8> string) {
                         ^
packages/ffi/src/utf8.dart:54:10: Error: Type 'Pointer' not found.
  static Pointer<Utf8> toUtf8(String string) {
         ^^^^^^^
packages/ffi/src/utf8.dart:54:10: Error: Expected 0 type arguments.
  static Pointer<Utf8> toUtf8(String string) {
         ^
packages/ffi/src/utf16.dart:16:21: Error: Type 'Struct' not found.
class Utf16 extends Struct {
                    ^^^^^^
packages/ffi/src/utf16.dart:24:10: Error: Type 'Pointer' not found.
  static Pointer<Utf16> toUtf16(String s) {
         ^^^^^^^
packages/ffi/src/utf16.dart:24:10: Error: Expected 0 type arguments.
  static Pointer<Utf16> toUtf16(String s) {
         ^
packages/ffi/src/allocation.dart:9:7: Error: Type 'DynamicLibrary' not found.
final DynamicLibrary stdlib = Platform.isWindows
      ^^^^^^^^^^^^^^
packages/ffi/src/allocation.dart:13:29: Error: Type 'Pointer' not found.
typedef PosixMallocNative = Pointer Function(IntPtr);
                            ^^^^^^^
packages/ffi/src/allocation.dart:13:46: Error: Type 'IntPtr' not found.
typedef PosixMallocNative = Pointer Function(IntPtr);
                                             ^^^^^^
packages/ffi/src/allocation.dart:14:23: Error: Type 'Pointer' not found.
typedef PosixMalloc = Pointer Function(int);
                      ^^^^^^^
packages/ffi/src/allocation.dart:18:27: Error: Type 'Void' not found.
typedef PosixFreeNative = Void Function(Pointer);
                          ^^^^
packages/ffi/src/allocation.dart:18:41: Error: Type 'Pointer' not found.
typedef PosixFreeNative = Void Function(Pointer);
                                        ^^^^^^^
packages/ffi/src/allocation.dart:19:35: Error: Type 'Pointer' not found.
typedef PosixFree = void Function(Pointer);
                                  ^^^^^^^
packages/ffi/src/allocation.dart:23:31: Error: Type 'Pointer' not found.
typedef WinGetProcessHeapFn = Pointer Function();
                              ^^^^^^^
packages/ffi/src/allocation.dart:26:7: Error: Type 'Pointer' not found.
final Pointer processHeap = winGetProcessHeap();
      ^^^^^^^

And so on.....

有没有办法将编译器配置为只为各自的运行构建与 Web 或 Mobile 相关的文件?

供参考:Github repo 重新创建了错误:https://github.com/JoshMarkF/MoorFFIIntegrationDemo

【问题讨论】:

    标签: flutter dart ffi flutter-web


    【解决方案1】:

    编辑
    flutter build webflutter run -d chrome 一切正常。
    因为 web ui 代码 (webui.dart) 和移动 ui 代码 (mobileui.dart) 在不同的 dart 文件中,
    所以这两个文件可以有不同的import

    您可以复制粘贴运行3下面三个文件,main.dartwebui.dartmobileui.dart
    您可以使用conditional import 来区分不同的网络和移动工具
    所以网络和移动可以有完全不同的逻辑

    使用前缀 multiPlatform 编码 sn-p 调用

    import 'mobileui.dart' if (dart.library.html) 'webui.dart' as multiPlatform;
    ...
    home:  multiPlatform.TestPlugin(),
    

    使用Android Studio 时的工作演示与Android EmulatorChrome 一起运行

    main.dart

    import 'package:flutter/material.dart';
    import 'mobileui.dart' if (dart.library.html) 'webui.dart' as multiPlatform;
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget { 
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(        
            primarySwatch: Colors.blue,
          ),
          home:  multiPlatform.TestPlugin(),
        );
      }
    }
    

    mobileui.dart

    import 'package:flutter/material.dart';
    
    class TestPlugin extends StatefulWidget {
      @override
      _TestPluginState createState() => _TestPluginState();
    }
    
    class _TestPluginState extends State<TestPlugin> {
      @override
      Widget build(BuildContext context) {
        return Text("Mobile");
      }
    }
    

    webui.dart

    import 'package:flutter/material.dart';
    import 'dart:html' as html;
    import 'dart:js' as js;
    import 'dart:ui' as ui;
    
    
    class TestPlugin extends StatefulWidget {
      TestPlugin();
    
      _TestPluginState createState() => _TestPluginState();
    }
    
    class _TestPluginState extends State<TestPlugin> {
      String createdViewId = 'map_element';
    
      @override
      void initState() {
        // ignore: undefined_prefixed_name
        ui.platformViewRegistry.registerViewFactory(
            createdViewId,
                (int viewId) => html.IFrameElement()
              ..width = MediaQuery.of(context).size.width.toString() //'800'
              ..height = MediaQuery.of(context).size.height.toString() //'400'
              ..srcdoc = """<!DOCTYPE html><html>
              <head><title>Page Title</title></head><body><h1>This is a Heading</h1><p>This is a paragraph.</p></body></html>"""
            /*..src = "http://f12apidev32.umc.com/Tableau/jsapi_practice.aspx"*/
              ..style.border = 'none');
    
        super.initState();
      }
    
      @override
      void dispose() {
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
            padding: EdgeInsets.symmetric(horizontal: 10),
            decoration: BoxDecoration(
                color: Colors.white,
                border: Border.all(color: Colors.grey[300], width: 1),
                borderRadius: BorderRadius.all(Radius.circular(5))),
            width: 200,
            height: 200,
            child: Directionality(
                textDirection: TextDirection.ltr,
                child: HtmlElementView(
                  viewType: createdViewId,
                )));
      }
    }
    

    【讨论】:

    • 在我的代码中,错误是由移动代码中的moor_ffi包引起的,web不需要,只有移动需要dart:ffi。有没有办法根据移动设备或网络控制这些导入?
    • 因为 webui.dart 和 mobileui.dart 是两个不同的 dart 文件。你不会遇到编译错误。你可以有完全不同的工具,当然还有不同的导入。你所需要的只是不同的 dart 文件。
    • 你可以看到我的例子 webui.dart 和 mobileui.dart 有完全不同的导入
    • 问题是flutter build webflutter run -d chrome 没有使用与here 描述的相同的编译器。简而言之,flutter build web 使用 dart2js,它将查看入口文件并仅编译 Web 代码。但是,flutter run -d chrome 使用 dartdevc 来查看 lib 文件夹中的所有文件。因此,它正在尝试编译移动文件和 moor_ffi,因此出现错误。
    • 我已经测试了我的演示。 flutter build web 工作,当我把它放在 IIS 中时也可以工作。您可以复制粘贴并测试我的案例。使用条件导入工作正常。
    猜你喜欢
    • 1970-01-01
    • 2020-05-25
    • 2021-04-02
    • 2018-10-24
    • 2019-12-28
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    相关资源
    最近更新 更多