setState没有更新UI

时间:2020-03-05 11:43:37

标签: flutter dart flutter-layout

我正在尝试从API提取数据,并且能够获取日志,但setState无法正常工作。 总的来说,我想要实现的是在屏幕上是否有响应显示数据,API或服务器上是否有错误或我想在小吃栏中显示任何其他内容。我的摩托车也要显示错误。

下面是我的模型课

import 'http.dart';

class User {
int userId;
int id;
String title;
String body;

User({this.userId, this.id, this.title, this.body});

User.fromJson(Map<String, dynamic> json) {
  userId = json['userId'];
  id = json['id'];
  title = json['title'];
  body = json['body'];
}

Map<String, dynamic> toJson() {
  final Map<String, dynamic> data = new Map<String, dynamic>();
  data['userId'] = this.userId;
  data['id'] = this.id;
  data['title'] = this.title;
  data['body'] = this.body;
  return data;
}


}


class UserExt {

static getUserInfo(Function(User user) success, Function(String errorMesssage) error) async{

  final response = await HTTP.get(api: "https://jsonplaceholder.typicode.com/posts/1");
  if(response.isSuccess == true) {
    success(User.fromJson(response.response));
  } else {
    error(response.response);
  }

}

}

下面是我的http.dart文件

import 'dart:html';
import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as http;
import 'dart:convert' as convert;
import 'package:http/http.dart';

const _timeoutDuration = Duration(seconds: 5);

class HTTP {


  static Future<HttpResponse> get({@required String api}) async {

    try {
      Response response = await http.get(api).timeout(_timeoutDuration);
      return _modeledResponse(response);
    } catch (error) {
      return HttpResponse(isSuccess: false, response: error.toString());
    }


  }

  static Future<HttpResponse> _modeledResponse(Response response) async {

    try {
      if(response.statusCode == HttpStatus.ok) {
        var jsonResponse = convert.jsonDecode(response.body);
        return HttpResponse(isSuccess: true, response: jsonResponse);
      } else {
        return HttpResponse(isSuccess: false, response: response.statusCode.toString());
      }
    } catch (error) {
      return HttpResponse(isSuccess: false, response: error.toString());
    }

  }



}




class HttpResponse {
  final bool isSuccess;
  final dynamic response;
  HttpResponse({@required this.isSuccess, @required this.response});
}

下面是我调用API的屏幕。

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http_request/User.dart';
import 'http.dart';






class ApiCalling extends StatefulWidget {
  @override
  _ApiCallingState createState() => _ApiCallingState();
}

class _ApiCallingState extends State<ApiCalling> {

  bool showLoader = false;

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: Center(
        child: Stack(
          children: <Widget>[


            Center(
              child: RaisedButton(
                child: Text("Call API"),
                onPressed: () {

                  setState(() {
                    showLoader = true;
                  });
                  UserExt.getUserInfo((user){
                    print("UUUser id = ${user.userId}");
                    Scaffold.of(context).showSnackBar(SnackBar(content:     Text("${user.userId}"),));

                setState(() {
                  showLoader = false;
                });


              }, (error){
                Scaffold.of(context).showSnackBar(SnackBar(content: Text("${error}"),));
                setState(() {
                  showLoader = false;
                });
              });


            },
          ),
        ),
        Visibility(child: CircularProgressIndicator(backgroundColor: Colors.pink,), visible: showLoader,),


      ],
    ),
  ),
);
  }
}

在当前代码中,指示器未显示/隐藏或小吃栏也未显示。

3 个答案:

答案 0 :(得分:3)

只需进行以下更改和加载项,只需检查以下代码即可:

import 'package:flutter/material.dart';
import 'package:sample_project_for_api/model.dart';

void main() => runApp(ApiCalling());

class ApiCalling extends StatefulWidget {
  @override
  _ApiCallingState createState() => _ApiCallingState();
}

class _ApiCallingState extends State<ApiCalling> {
  bool showLoader = false;
  final _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        key: _scaffoldKey,
        body: Center(
          child: Stack(
            children: <Widget>[
              Builder(
                builder: (context) {
                  return Column(
                    children: <Widget>[
                      RaisedButton(
                        child: Text(
                            "this is first api call under the builder widget"),
                        onPressed: () {
                          UserExt.getUserInfo((user) {
                            print("UUUser id = ${user.userId}");
                            Scaffold.of(context).showSnackBar(SnackBar(
                              backgroundColor: Colors.redAccent,
                              content:
                                  Text("This is you user id ${user.userId}"),
                            ));
                          }, (error) {
                            Scaffold.of(context).showSnackBar(SnackBar(
                              duration: Duration(seconds: 2),
                              backgroundColor: Colors.redAccent,
                              content: Text("${error.toString()}"),
                            ));
                          });
                        },
                      ),
                      RaisedButton(
                        child: Text(
                            "this is second api call under the builder widget"),
                        onPressed: () {
                          UserExt.getUserInfo((user) {
                            print("UUUser id = ${user.userId}");
                            Scaffold.of(context).showSnackBar(SnackBar(
                              backgroundColor: Colors.redAccent,
                              content:
                                  Text("This is you user id ${user.userId}"),
                            ));
                          }, (error) {
                            Scaffold.of(context).showSnackBar(SnackBar(
                              duration: Duration(seconds: 2),
                              backgroundColor: Colors.redAccent,
                              content: Text("${error.toString()}"),
                            ));
                          });
                        },
                      )
                    ],
                  );
                },
              ),
              Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    RaisedButton(
                      child: Text("call snacker using the global key"),
                      onPressed: () {
                        setState(() {
                          showLoader = true;
                        });
                        UserExt.getUserInfo((user) {
                          print("UUUser id = ${user.userId}");
                          _scaffoldKey.currentState.showSnackBar(new SnackBar(
                              duration: Duration(seconds: 2),
                              content: new Text(
                                  "This is you user id :${user.userId}")));

                          setState(() {
                            showLoader = false;
                          });
                        }, (error) {
                          _scaffoldKey.currentState.showSnackBar(new SnackBar(
                              duration: Duration(seconds: 2),
                              content: new Text("${error.toString()}")));

                          setState(() {
                            showLoader = false;
                          });
                        });
                      },
                    ),
                    Secondbutton(),
                  ],
                ),
              ),
              Visibility(
                child: CircularProgressIndicator(
                  backgroundColor: Colors.pink,
                ),
                visible: showLoader,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class Secondbutton extends StatefulWidget {
  @override
  _SecondbuttonState createState() => _SecondbuttonState();
}

class _SecondbuttonState extends State<Secondbutton> {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      child: Text("calling snacker without using the global key"),
      onPressed: () {
        UserExt.getUserInfo((user) {
          print("UUUser id = ${user.userId}");
          Scaffold.of(context).showSnackBar(SnackBar(
            backgroundColor: Colors.redAccent,
            content: Text("This is you user id ${user.userId}"),
          ));
        }, (error) {
          Scaffold.of(context).showSnackBar(SnackBar(
            duration: Duration(seconds: 2),
            backgroundColor: Colors.redAccent,
            content: Text("${error.toString()}"),
          ));
        });
      },
    );
  }
}


您的问题是因为没有获得适当的上下文。

答案 1 :(得分:2)

颤抖的官方文档https://api.flutter.dev/flutter/material/Scaffold/of.html

当在同一构建函数中实际创建Scaffold时,构建函数的context参数不能用于查找Scaffold(因为它在窗口小部件树中返回的窗口小部件“上方”)。在这种情况下,可以使用以下带有Builder的技术来为BuildContext提供“位于”脚手架下方的新作用域:

因此,基本上问题在于您的Scaffold上下文,因此,与其使用实例化Scaffold的直接父级上下文,不如使用子级上下文。

下面的代码将起作用。

class _ApiCallingState extends State<ApiCalling> {
  bool showLoader = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Builder(
        builder: (context)=>
            Center(
        child: Stack(
          children: <Widget>[
            Center(
              child: RaisedButton(
                child: Text("Call API"),
                onPressed: () {
                  setState(() {
                    showLoader = true;
                  });
                  UserExt.getUserInfo((user) {
                    print("UUUser id = ${user.userId}");
                    print("context==$context");
                    Scaffold.of(context).showSnackBar(SnackBar(
                      content: Text(" User Id${user.userId}"),
                    ));
                     setState(() {
                      showLoader = false;

                    });



                  }, (error) {
                    setState(() {
                      showLoader = false;
                    });
                    Scaffold.of(context).showSnackBar(SnackBar(
                      content: Text("${error}"),
                    ));

                  });
                },
              ),
            ),
            Visibility(
              child:
              Center(
                child:CircularProgressIndicator(
                  backgroundColor: Colors.pink,
                ),

              ),
              visible: showLoader,
            )
          ],
        ),
      ),
      )

    );
  }
}

答案 2 :(得分:-1)

声明全局密钥 final _scaffoldKey = GlobalKey();

和用户界面中 _scaffoldKey.currentState.showSnackBar(snackbar);