从外部模型类更改Flutter小部件状态

时间:2020-07-07 18:53:01

标签: flutter dart

我正在构建一个Flutter应用程序。我希望UI部分和逻辑部分保持分开,所以我将所有代码放在单独的类(不是小部件)中。

我的主窗口小部件文件

import "package:flutter/material.dart";
import 'package:google_sign_in/google_sign_in.dart';
import 'package:appname/Models/user.dart';

final GoogleSignIn googleSignIn = GoogleSignIn();

class googleLogin extends StatefulWidget {
  @override
  _googleLoginState createState() => _googleLoginState();
}

class _googleLoginState extends State<googleLogin> {
  User user = new User();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:Container(
        child:Column(
          children: <Widget>[
            MaterialButton(
              padding: EdgeInsets.only(top:50),
              onPressed: (){
                setState(() {
                  user.signInWithGoogle();
                });
              },
              child: Text("Log In")
            ),
            MaterialButton(
                padding: EdgeInsets.only(top:100),
                onPressed: (){
                  setState(() {
                    user.signOutWithGoogle();
                  });
                },
                child: Text("Log Out")
            ),
            if(user.username!="") Text(user.username),
            if(user.email!="")Text(user.email),
            if(user.imageurl!="") Image.network(user.imageurl),
          ],
        )
      )
    );
  }
}

我的用户模型类

import 'dart:convert';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:appname/GoogleSignIn/GoogleSignIn.dart';
import 'package:http/http.dart' as http;

class User{
  String _username="";
  String _email="";
  String _imageurl="";

  String get imageurl=>_imageurl;
  String get email => _email;
  String get username => _username;

  Future<void> signInWithGoogle() async {
    final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
    print(googleSignInAccount.displayName);
    this._username = googleSignInAccount.displayName;
    this._email = googleSignInAccount.email;
    this._imageurl = googleSignInAccount.photoUrl;
    createUser(googleSignInAccount.displayName, googleSignInAccount.email);
    print('signInWithGoogle succeeded');
  }

  void signOutWithGoogle() async{
    await googleSignIn.signOut();
    this._username="";
    this._email = "";
    this._imageurl="";
    print("User Sign Out");
  }

  Future<http.Response> createUser(String name, String email) async {
    return http.post(
      'http://172.20.10.3:8000/createuser/',
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: jsonEncode(<String, String>{
        'name':name,
        'email':email
      }),
    );
  }
}

我期望-单击“登录”按钮时,User类中的变量值会更改。因此,我希望稍后在第一个代码文件中的Text小部件显示用户的姓名和电子邮件。

会发生什么-当我单击“登录”按钮时,变量的值已更改,但是Text字段未更改。

我在setState上使用了onPressed(),所以我只是希望状态会被更新。请帮忙。

注意-我已提及Flutter setState to another class?Flutter: Calling SetState() from another classIs it possible to change the state of another class using a button which is located at somewhere else in the widget tree 但它们不能解决我的问题。

1 个答案:

答案 0 :(得分:0)

您没有等待任何异步功能,因此setState将在更改不同变量的值之前完成。

使用await关键字意味着您在继续执行之前等待方法执行结束。

您需要将代码更改为类似的内容

        MaterialButton(
          padding: EdgeInsets.only(top:50),
          onPressed: () async {
            await user.signInWithGoogle();
            setState(() {});
          },
          child: Text("Log In")
        ),
        MaterialButton(
            padding: EdgeInsets.only(top:100),
            onPressed: () async {
              await user.signOutWithGoogle();
              setState(() {});
            },
            child: Text("Log Out")
        ),

并更改signOutWithGoogle以返回未来

Future signOutWithGoogle() async{
   ...
}