【问题标题】:How to call method from another class in Flutter(Dart)?如何从 Flutter(Dart) 中的另一个类调用方法?
【发布时间】:2019-03-04 02:29:12
【问题描述】:

我创建了一个主页,用户可以从该主页登录该应用,然后在下一个屏幕中,用户可以看到他们的个人资料信息(仅个人资料名称),并且在该页面下方是他们的退出按钮。用户可以使用注销按钮从应用程序中注销。但这对我不起作用。

我想通过按 details.dart 中的 signOut 按钮从 main.dart 调用 signOut 方法(两个类都在不同的文件中)

但是当我在 details.dart 中按下 signOut 按钮时没有任何反应!

代码如下:

main.dart

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'details.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  MyHomePageState createState() => MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
  final  GoogleSignIn googleSignIn = GoogleSignIn();
  static bool _LoginButton = true;

  void signOut(){
    googleSignIn.signOut();
    setState((){
      _LoginButton = true;
    });
    print(_LoginButton);
    print("User Signed Out");
  }

  Future<FirebaseUser> _signIn() async{
    if(_LoginButton==true){
      setState((){
        _LoginButton=false;
      });
      GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
      GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;
      FirebaseUser firebaseUser = await firebaseAuth.signInWithGoogle(idToken: googleSignInAuthentication.idToken, accessToken: googleSignInAuthentication.accessToken);
      print("Username is "+firebaseUser.displayName);
      setState((){
        _LoginButton = true;
      });
      Navigator.push(context, MaterialPageRoute(builder: (context) => details(firebaseUser.displayName,signOut)));

      return firebaseUser;
    }
  }

  bool _LoginButtonBool(){
    return _LoginButton;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Google auth with firebase"),),
      body: Center(
        child: _LoginButtonBool()?Container(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              MaterialButton(onPressed: _LoginButtonBool() ? () => _signIn().then((FirebaseUser firebaseuser ) =>print(firebaseuser)).catchError((e) => print(e)): null,
              child: Text("Login"),color: Colors.orange,),
            ],
          ),
        ):CircularProgressIndicator(backgroundColor: Colors.greenAccent.withOpacity(0.01),),
      ),
    );
  }
}

details.dart

import 'package:flutter/material.dart';
import 'package:flutter_auth/main.dart';

class details extends StatelessWidget {
  String name;
  final Function callback;
  details(this.name,this.callback);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:Center(child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          Text(name),
          MaterialButton(onPressed: () => callback,
          child: Text("Log out"),color: Colors.orange),
        ],
      ),),
    );
  }
}

【问题讨论】:

  • 您是否尝试过使用回调? stackoverflow.com/questions/51029655/…
  • 我尝试使用回调,但我收到一条错误消息:“此处的表达式的类型为 'void',因此无法使用。
  • 在 details.dart 中:将 MaterialButton(onPressed: () => 回调更改为 MaterialButton(onPressed: () => callback(),尽管这不会解决您在这里尝试做的事情,但不会推送你回到登录屏幕。
  • @anmol.majhail 我不知道为什么,但这对我有用!!谢谢,如果你能解释一下,那对我来说会更好。
  • @yash1173 要执行一个函数,我们需要调用一个带括号的函数。你只是在引用没有执行它的函数。

标签: dart flutter


【解决方案1】:

在 DetailsPage 中导入 HomePage 类并从中创建一个新实例,然后调用您想要的方法(如果它是公共方法)。

【讨论】:

  • 我确信它不会工作,因为我无法创建它的对象。
【解决方案2】:

您必须小心您正在尝试执行的操作,因为您可能正在访问未安装的页面/小部件。想象一下你做了一个pushReplacement(new MaterialPageroute(...))。上一页在树中不再可用,因此您无法访问它,也无法访问它的任何方法。

除非您的树中有明确的父子关系,否则您应该将您的逻辑抽象为外部或业务逻辑类。因此,您确信您正在调用您的类的活动实例。

下面是一个可以用来传递业务对象的示例。如果你使用其他模式,如 BLOC、ScopedModel、Streams 等,那就更好了。但为了简单起见,我认为这应该足够了。

import "package:flutter/material.dart";

void main() {
  runApp(MyApp(new Logic()));
}

class Logic {
  void doSomething() {
    print("doing something");
  }
}

class MyApp extends StatelessWidget {
  final Logic logic;

  MyApp(this.logic);

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new HomePage(widget.logic),
    );
  }
}

class HomePage extends StatelessWidget {
  final Logic logic;

  HomePage(this.logic);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FlatButton(
          onPressed: () { Navigator.of(context).pushReplacement(
             MaterialPageRoute(
               builder: (context) => AnotherPage(logic),
             ))},
          child: Text("Go to AnotherPage"),
        ),
      ),
    );
  }
}

class AnotherPage extends StatelessWidget {
  final Logic logic;

  AnotherPage(this.logic);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FlatButton(
          onPressed: logic.doSomething,
          child: Text("Press me"),
        ),
      ),
    );
  }
}

如果您仍想调用另一个页面中的函数并且您确定该页面已安装(您已完成push 而不是pushReplacement),您可以执行以下操作。 (小心处理)

class HomePage extends StatelessWidget {

  HomePage();

  void onCalledFromOutside() {
    print("Call from outside");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
    child: FlatButton(
          onPressed: () { Navigator.of(context).push(
             MaterialPageRoute(
               builder: (context) => AnotherPage(onCalledFromOutside),
             ))},
          child: Text("Go to AnotherPage"),
        ),
      ),
    );
  }
}

class AnotherPage extends StatelessWidget {
  final Function callback

  AnotherPage(this.callback);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
    child: FlatButton(
           onPressed: callback,
           child: Text("Press me"),
        ),
      ),
    );
  }
}

【讨论】:

  • 大家好,我该如何在 main.dart 的路线上使用参数?
  • 好吧,你不能将参数传递给路由本身,但你可以将参数传递给你正在构建的小部件的构造函数(如上面的 bloc 参数)o 使用RouteSettings 作为@ rémi-rousselet 建议在stackoverflow.com/questions/47419908
【解决方案3】:

您可以创建另一个 logout() 函数并提供主页的上下文以推回登录屏幕/主屏幕,对我来说是:

      logout() async {
        await googleSignIn.signOut();
        Navigator.push(context, MaterialPageRoute(builder: (context) => Home()));
      }

【讨论】:

    【解决方案4】:

    很简单,我举个例子来解释

    class Animals
    {
      var animalList = ['dog','cat','cow'];
    
      // function for printing the list of animals
    
      void animalListPrinter(){
        for(var animal in animalList){
            print(animal);
    
         }
      }
    }
    

    将上述函数调用到另一个类

    class ShowingAnimalList extends StatelessWidget {
         final Animals ani= new Animals();
         @override
         Widget build(BuildContext context) {
           return GestureDetector(
             onTap:()=> ani.animalListPrinter(),
           );
      }
    }
    

    你可以用这个从父类调用任何Widget

    【讨论】:

      【解决方案5】:

      我们可以像下面一样轻松访问它。

      className().MethodName(),
      

      【讨论】:

        【解决方案6】:

        我们可以帮助实例制作下面给出的实例

        var objectName = new ClassName()

        注意:我们可以像这个例子一样使用一个空的构造函数。

         class Student{
        void female(){
        print('This is female method');
        }
        void male(){
        print('This is malemethod'); }
        }
        

        第一步: var _instance1 = new Student();这里空的构造函数没关系。

        第二步:_instance1.male();调用我们想要的方法_instance1。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-03-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-07-25
          • 1970-01-01
          相关资源
          最近更新 更多