如何在Dart/Flutter中使用另一个文件的功能?

Cha*_* Jr 23 methods function dart flutter

我有一个Flutter应用程序,我正在使用flutter_web_view包.我在几个不同的文件中使用它,并且很乐意创建自己的文件,并且只需在我的应用程序中的任何地方使用_launchwebview函数进行引用,因为需要几行代码才能使其工作.我知道如何引用文件和传递信息,但不知道方法/函数.这是班级代码......

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

class ShopClass extends StatefulWidget {
  @override
  ShopClassState createState() => new ShopClassState();
}

class ShopClassState extends State<ShopClass> {
  String _redirectedToUrl;
  FlutterWebView flutterWebView = new FlutterWebView();
  bool _isLoading = false;

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

  @override
  Widget build(BuildContext context) {
    Widget leading;
    if (_isLoading) {
      leading = new CircularProgressIndicator();
    }
    var columnItems = <Widget>[
      new MaterialButton(
          onPressed: launchWebViewExample, child: new Text("Launch"))
    ];
    if (_redirectedToUrl != null) {
      columnItems.add(new Text("Redirected to $_redirectedToUrl"));
    }
    var app = new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          leading: leading,
        ),
        body: new Column(
          children: columnItems,
        ),
      ),
    );
    return app;
  }


  void launchWebViewExample() {
    if (flutterWebView.isLaunched) {
      return;
    }

    flutterWebView.launch("https://apptreesoftware.com",
        headers: {
          "X-SOME-HEADER": "MyCustomHeader",
        },
        javaScriptEnabled: false,
        toolbarActions: [
          new ToolbarAction("Dismiss", 1),
          new ToolbarAction("Reload", 2)
        ],
        barColor: Colors.green,
        tintColor: Colors.white);
    flutterWebView.onToolbarAction.listen((identifier) {
      switch (identifier) {
        case 1:
          flutterWebView.dismiss();
          break;
        case 2:
          reload();
          break;
      }
    });
    flutterWebView.listenForRedirect("mobile://test.com", true);

    flutterWebView.onWebViewDidStartLoading.listen((url) {
      setState(() => _isLoading = true);
    });
    flutterWebView.onWebViewDidLoad.listen((url) {
      setState(() => _isLoading = false);
    });
    flutterWebView.onRedirect.listen((url) {
      flutterWebView.dismiss();
      setState(() => _redirectedToUrl = url);
    });
  }



  void reload() {
    flutterWebView.load(
      "https://google.com",
      headers: {
        "X-SOME-HEADER": "MyCustomHeader",
      },
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能launchWebViewExample在另一堂课中使用?

Ant*_*ace 38

您可以使用该函数编写文件,例如:

test.dart

void launchWebView () {
  print("1234");
}
Run Code Online (Sandbox Code Playgroud)

然后像这样导入该文件:

main.dart

import "test.dart";

class _MyHomePageState extends State<MyHomePage> {
   @override
   Widget build(BuildContext context) {
       launchWebView();
Run Code Online (Sandbox Code Playgroud)

它不是很干净,但你可以做到这一点.或者,您可以使用具有静态方法的类,如:

class test {
    static void foo() {
        print("1234");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的代码中调用它(导入后):

test.foo();
Run Code Online (Sandbox Code Playgroud)

  • 我已经思考这两个选项很长一段时间了。您能否详细说明这两个选项的优缺点。第一个选项听起来不像是经验法则选项,对吧?虽然,我不知道为什么。你能解释一下为什么吗?另一方面,我读到最好避免静态方法/变量,因为它们会占用内存。但就记忆而言,第一个选项不是同样的故事吗?换句话说,如果我不创建一个类,只是在文件中使用函数,那么每个函数不会自动成为静态函数吗? (3认同)
  • 我成功打印了一条语句,但在类中执行 launchWebView 函数时遇到了一些问题。有任何想法吗? (2认同)
  • @Antonino Cacace 你说顶级函数在 flutter 中并不是很干净。但为什么?他们在官方文档中是这样说的:“注意:对于常见或广泛使用的实用程序和功能,考虑使用顶级函数而不是静态方法。” https://dart.dev/guides/language/language-tour#adding-features-to-a-class-mixins#static-methods (2认同)

Pra*_*tti 16

使用mixin而不是全局函数!

为什么会出现这种情况?

我在几个不同的文件中使用它,并且希望创建自己的文件并在应用程序中的任何位置引用 _launchwebview 函数,因为需要几行代码才能使其工作。

带下划线的方法是给定库私有的。因此,如果我们_launchwebview在一个文件中定义,则该函数位于一个迷你库(Source)中。因此,该方法只能在该文件中访问。我探索了如何跨文件公开私有方法,但发现解决方案很混乱。因此,我认为使用公共函数可以更好地回答这个问题。问题是在不同的类中实现共享功能,而不是简单地提供访问。

我选择为这个特定问题添加此解决方案,因为该方法(启动 Web 视图)最好在每个适当的Widget类中实现。请注意,扩展方法在这种情况下也可以工作,但 Flutter 更喜欢组合而不是继承。

如果我们想将公共的(即非下划线的方法)移动到不同的类而不进行复制粘贴,我们可以尝试几种概述的方法。我在下面详细介绍了现有选项的缺点。

黑客解决方案

  1. 使用该part指令使我们能够通过私有实现复制一个文件的源代码并在另一个文件中使用它。但这是不鼓励的,因为该技术增加了二进制大小,违背了Effective Dart使用指南,并且显然是一种代码味道,因为我们复制粘贴相同的代码。
  2. 使用全局函数不遵循面向对象编程。全局状态打破了封装原则。由于语言的设计方式(类),OOP 是在 Dart 应用程序中使用的最佳范例。最佳答案推荐全局函数,但是,考虑到 Dart 强大的语言功能,这应该是最后的手段。
  3. 静态函数打破了封装和开闭原则。它们很难与状态管理解决方案集成,因为我们跟踪实例方法上下文中的状态。例如,集成provider和其他包,如GetX.
  4. 将 a 定义Function为类的属性可能会导致进一步的微妙错误。例如,我们可以将任何函数分配给该属性,因为没有函数签名类型检查。此外,这不是一个具有代码重复的可扩展解决方案。

解决方案:混合

当我们想要减少重复代码但避免扩展整个类时,Dart 内置支持选择性地向类添加函数(源代码)。关键字mixin通过将类与某些特定逻辑混合来实现此目的。如果需要,我们可以将其限制mixin为特定的子类on

代码示例

LaunchWebView.dart

mixin LaunchWebView on StatelessWidget { // you can also constrain the mixin to specific classes using on in this line.
  void launchWebView() {
    // Add web view logic here. We can add variables to the mixin itself as well.
  }
}
Run Code Online (Sandbox Code Playgroud)

用法

class ExampleClass extends StatelessWidget with LaunchWebView {
  Widget build(BuildContext context) {
    ....
  }

  void testFunction() {
    // We now have access to launchWebView().
    launchWebView();
  }
}
Run Code Online (Sandbox Code Playgroud)


Cop*_*oad 7

您可以通过不同的方式做到这一点:

1. 全局函数:

在文件中定义您的函数,例如global.dart

void func() => print('Hello');
Run Code Online (Sandbox Code Playgroud)

要在任何文件中使用它,只需调用:

func();
Run Code Online (Sandbox Code Playgroud)

2.类中的静态函数:

创建一个类,Foo并在其中定义您的函数:

class Foo {
  static void func() => print('Hello');
}
Run Code Online (Sandbox Code Playgroud)

要在任何文件中使用它,只需调用

Foo.func();
Run Code Online (Sandbox Code Playgroud)

3.使用mixin:


Mah*_*mat 5

或者,您可以只在一个类中声明所有函数(帮助器),然后将它们作为参数传递给其他类。

//The class which contains your functions
class HelperFunction{

  //Define your method
  void launchWebView () {
    print("1234");
  }

  //Pass that function to a class
  MyHomePage(launchWebView);

}

//The class which receives the function.
class MyHomePage extends StatefulWidget{
  //Retrieve the function and store it to a variable of type Function.
  final Function launchWebView;
  MyHomePage(this.launchWebView);
}

class _MyHomePageState extends State<MyHomePage> {
   @override
   Widget build(BuildContext context) {
     //Access that function in State class using widget keyword.
     widget.launchWebView();
   }
}  
Run Code Online (Sandbox Code Playgroud)