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

Posted

技术标签:

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

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

我想通过按 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),
        ],
      ),),
    );
  

【问题讨论】:

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

您必须小心您正在尝试执行的操作,因为您可能正在访问未安装的页面/小部件。想象一下你做了一个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 建议在***.com/questions/47419908【参考方案2】:

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

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

【讨论】:

【参考方案3】:

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

className().MethodName(),

【讨论】:

【参考方案4】:

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

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

【讨论】:

【参考方案5】:

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

【讨论】:

我确信它不会工作,因为我无法创建它的对象。【参考方案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。

【讨论】:

以上是关于如何从 Flutter(Dart) 中的另一个类调用方法?的主要内容,如果未能解决你的问题,请参考以下文章

将 API 数据从第 1 页传递到 Flutter 上的另一个 dart 页面

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

如何使用 Dart / Flutter 中的列表从列表中删除重复元素?

如何从 Flutter 中的另一个路由/页面增加计数器

如何在 Flutter dart 的列表中的循环内附加数据?

将快照数据从一个 dart 文件传递​​到颤振项目中的另一个文件