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

时间:2018-02-17 00:13:08

标签: function methods 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",
      },
    );
  }
}

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

4 个答案:

答案 0 :(得分:21)

您可以使用该功能编写文件,例如:

test.dart

public class MyWebView extends WebView
{
    protected String m_szFocusInputID = "";

    public void onStartLoad()
    {
        WebSettings oWebSettings = getSettings();
        oWebSettings.setJavaScriptEnabled(true);
        ... 
        m_oClient = new WebViewClientEx();
        setWebViewClient(m_oClient);
        ...
        addJavascriptInterface(new JSBridge( ), "MyApp");
        loadUrl("file:///android_asset/myfile.html"); 
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo oAttrs)
    {
        InputConnection oConn = super.onCreateInputConnection(oAttrs);

        if ("someid".compareTo(m_szFocusInputID) == 0)
        {
            oAttrs.inputType = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL;
        }
        return oConn;
    }


    private class WebViewClientEx extends WebViewClient
    {
        @Override
        public void onPageFinished(WebView oView, String szUrl)
        {
            evaluateJavascript("$('#myinput1').focusin(function() { MyApp.onFocusIn(this.id); });", null);      
        }
    }


    public class JSBridge extends Object
    {
     ...
        @android.webkit.JavascriptInterface
        public void onFocusIn(String szFocusInputID)
        {
            m_szFocusInputID = szFocusInputID;
        }
    }   
}

然后像这样导入该文件:

main.dart

void launchWebView () {
  print("1234");
}

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

import "test.dart";

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

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

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

答案 1 :(得分:3)

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

//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 class _MyHomePageState extends State<MyHomePage> {
   @override
   Widget build(BuildContext context) {
     //Access that function in State class using widget keyword.
     widget.launchWebView();
   }
}  

答案 2 :(得分:2)

为什么会这样?

<块引用>

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

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

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

如果我们想在不复制粘贴的情况下将一个公共的,即非下划线的方法移动到一个不同的类,我们可以尝试几种概述的方法(见下文)。

hacky 解决方案

  1. 使用 part 指令使我们能够复制具有私有实现的一个文件的源并在另一个文件中使用它。但不鼓励这样做,因为该技术增加了二进制文件的大小,违反了 Effective Dart 使用指南,并且不是一个优雅的解决方案。
  2. 使用全局函数不是好的面向对象编程,因为它们违反了封装原则。最佳答案推荐了这种方法,我认为可以进一步改进答案。我写这个答案是为了提供替代解决方案。
  3. 静态函数也打破了封装和开闭原则。它们还使我们难以与状态管理解决方案集成,因为我们应该在实例方法上下文(如 provider 和其他知名包)中跟踪状态。

解决方案:混合

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

所以我们可以先在一个新文件中添加共享代码:

mixin LaunchWebView { // 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 Musician with LaunchWebView {
  void testFunction() {
    // We now have access to launchWebView().
    launchWebView();
  }
}

答案 3 :(得分:-1)

您想要在类级别声明函数

file foo.dart

class foo {

  void launchWebView () {};

}

file bar.dart

import 'foo.dart'
class Bar {

  void someFunction (){
    launchWebView();
  }


}