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

Posted

技术标签:

【中文标题】如何在 Dart / Flutter 中使用另一个文件的函数?【英文标题】:How to use Functions of another File in Dart / Flutter? 【发布时间】:2018-07-27 22:40:51 【问题描述】:

我有一个 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",
      ,
    );
  

如何在另一个班级中使用launchWebViewExample

【问题讨论】:

你能分享一些代码吗?目前还不清楚问题是什么。使用该功能导入文件应该可以。如果你想传递函数,那么字段或其他变量并没有真正的区别。 这是您要找的吗? ***.com/questions/12951989/… @GünterZöchbauer 我已经从我创建的文件中添加了代码。我想用它在另一个文件中启动 WebView 而不将所有这些行添加到每个文件中。 _ 在函数名前面将使其私有 _launchwebview, 【参考方案1】:

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

1。全局函数:

在一个文件中定义你的函数,比如global.dart

void func() => print('Hello');

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

func();

2。类中的静态函数:

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

class Foo 
  static void func() => print('Hello');

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

Foo.func();

3。使用 mixin:

如果你想在任何类中使用该函数:

创建一个mixin,比如Bar

mixin Bar 
  void func() => print('Hello');

要在类中使用它,只需使用 with 关键字后跟 mixin。

class Baz with Bar 
  void main() => func();

如果您想限制 mixin 不能与任何类一起使用:

class Foo 

创建一个mixin,比如Bar,它位于Foo

mixin Bar on Foo 
  void func() => print('Hello');

要使用 Bar mixin,我们需要扩展 Foo 类,因为它就是这样。

class Baz extends Foo with Bar 
  void main() => func();

【讨论】:

在全局函数部分,你也可以在其他文件中使用import 'global.dart' as global,然后使用global.func();调用函数【参考方案2】:

使用mixin 代替全局函数!

为什么会这样?

我在几个不同的文件上使用它,并且很想创建 它自己的文件和 _launchwebview 函数的引用 在我的应用程序中的任何地方,因为需要几行代码 为了使它工作。

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

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

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

黑客解决方案

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

解决方案:混入

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

代码示例

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.
  

用法

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

  void testFunction() 
    // We now have access to launchWebView().
    launchWebView();
  

【讨论】:

封装原则是良好的面向对象设计 (OOP) 的核心原则。这个想法说方法应该在对象实例上定义。公共方法仍然在对象上调用,因此它们不违反原则。我希望这会有所帮助。 看来你不知道你在说什么。我不是在谈论继承。 Mixin 是组合的一个例子。 先读懂什么是 OOP 怎么样?那么你就不会奇怪为什么方法比***函数更好。 这是将静态方法与***函数进行比较。我说的是实例方法如何优于***函数。如果您仍有疑问,请告诉我。【参考方案3】:

你想在类级别声明函数

文件 foo.dart

class Foo 

  static void launchWebView () ;


文件 bar.dart

import 'foo.dart'
class Bar 

  void someFunction ()
    Foo.launchWebView();
  



【讨论】:

如何在不引用该类的情况下直接调用其他类的方法?【参考方案4】:

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

//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();
   
  

【讨论】:

【参考方案5】:

你可以只用那个函数写一个文件,比如:

test.dart

void launchWebView () 
  print("1234");

然后像这样导入该文件:

main.dart

import "test.dart";

class _MyHomePageState extends State<MyHomePage> 
   @override
   Widget build(BuildContext context) 
       launchWebView();

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

class test 
    static void foo() 
        print("1234");
    

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

test.foo();

【讨论】:

我成功打印了一个语句,但是在类中执行launchWebView 函数时遇到了一点问题。有什么想法吗? 我一直在考虑这两个选项已经有一段时间了。您能否详细说明这两个选项的优缺点。第一个选项听起来不像是经验法则选项,对吧?虽然,我不知道为什么。你能解释一下为什么吗?另一方面,我读到最好避免使用静态方法/变量,因为它们会占用内存。但是,就记忆而言,第一个选项不是同一个故事吗?换句话说,如果我不创建一个类,文件中的函数不会自动每个函数都是静态的吗? @Antonino Cacace 你说***函数在颤振中并不是很干净。但为什么?这是他们在官方文档中所说的:“注意:对于常见或广泛使用的实用程序和功能,请考虑使用***函数,而不是静态方法。” dart.dev/guides/language/…

以上是关于如何在 Dart / Flutter 中使用另一个文件的函数?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Flutter(Dart) 中的另一个类调用方法?

如何从另一个 dart 文件中调用有状态小部件(有表单)方法?- Flutter

如何访问和更改在 FLUTTER/DART 的另一个类中声明的字符串变量的值

使用 Dart 和 Flutter,我如何将动态小部件中的数据保存到另一个列表中的地图列表中

如何导入依赖于 Flutter 平台的 Dart 文件或包?

检查数组是不是包含另一个数组及其在 DART/Flutter 中的位置