Dart 每5分钟或定期刷新颤振文本小部件内容

Dart 每5分钟或定期刷新颤振文本小部件内容,dart,flutter,flutter-animation,Dart,Flutter,Flutter Animation,我有一个flatterText小部件,它的内容是通过外部REST调用填充的。我想通过调用REST端点每隔5分钟定期刷新小部件内容 到目前为止,我设法每5分钟调用一次端点,但无法使用来自网络的新数据更新/刷新小部件内容 class PatientCount { int count; double amount; PatientCount({this.count, this.amount}); PatientCount.fromJson(Map<String, dynamic&

我有一个flatter
Text
小部件,它的内容是通过外部REST调用填充的。我想通过调用REST端点每隔5分钟定期刷新小部件内容

到目前为止,我设法每5分钟调用一次端点,但无法使用来自网络的新数据更新/刷新小部件内容

 class PatientCount {
  int count;
  double amount;

PatientCount({this.count, this.amount});

 PatientCount.fromJson(Map<String, dynamic> map)
  : count = map['count'],
    amount = map['amount'];
}

Future<PatientCount> fetchPatientCount() async {

  var url = "http://localhost:9092/hms/patients-count-on-day";

  Map<String, String> requestHeaders = new Map<String, String>();
  requestHeaders["Accept"] = "application/json";
  requestHeaders["Content-type"] = "application/json";

  String requestBody = '{"consultedOn":' + '16112018' + '}';  

  http.Response response =
  await http.post(url, headers: requestHeaders, body: requestBody);

  final statusCode = response.statusCode;
  final Map responseBody = json.decode(response.body);

  if (statusCode != 200 || responseBody == null) {
     throw new FetchPatientCountException(
    "Error occured : [Status Code : $statusCode]");
   }
    return PatientCount.fromJson(responseBody['responseData']. 
    ['PatientCountDTO']);
}    
class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
 }

class _MainPageState extends State<MainPage> {
@override
void initState() {
super.initState();
setState(() {
  const oneSecond = const Duration(seconds: 25);
  new Timer.periodic(oneSecond, (Timer t) => buildCountWidget());
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
    appBar: AppBar(
      elevation: 2.0,
      backgroundColor: Colors.white,
      title: Text('Dashboard'),
    ),
    body: StaggeredGridView.count(
      crossAxisCount: 2,
      crossAxisSpacing: 12.0,
      mainAxisSpacing: 12.0,
      padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
      children: <Widget>[
        _buildTile(
          Padding(
            padding: const EdgeInsets.all(24.0),
            child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Text(
                        'Today\'s OPD',
                        style: TextStyle(
                            color: Colors.blueAccent, fontSize: 18.0),
                      ),
                      buildCountWidget(),
                    ],
                  ),
                  Material(
                      color: Colors.blue,
                      borderRadius: BorderRadius.circular(24.0),
                      child: Center(
                          child: Padding(
                        padding: const EdgeInsets.all(16.0),
                        child: Icon(Icons.timeline,
                            color: Colors.white, size: 30.0),
                      )))
                ]),
          ),
        ),
      ],
      staggeredTiles: [StaggeredTile.extent(2, 110.0)],
    ));
  }

 Widget _buildTile(Widget child, {Function() onTap}) {
  return Material(
    elevation: 14.0,
    borderRadius: BorderRadius.circular(12.0),
    shadowColor: Color(0x802196F3),
    child: InkWell(
        // Do onTap() if it isn't null, otherwise do print()
        onTap: onTap != null
            ? () => onTap()
            : () {
                print('Not set yet');
              },
        child: child));
  }

 Widget buildCountWidget() {
 Widget vistitCount = new Center(
  child: new FutureBuilder<PatientCount>(
    future: fetchPatientCount(),
    builder: (context, snapshot) {          
      if (snapshot.connectionState == ConnectionState.done) {
        if (snapshot.hasData) {
          print(snapshot.data.count);
          /* below text needs to be updated every 5 mins or so */
          return new Text('#' + snapshot.data.count.toString(),
              style: TextStyle(
                  color: Colors.black,
                  fontWeight: FontWeight.w700,
                  fontSize: 34.0));
        } else if (snapshot.hasError) {
          return new Text("${snapshot.error}");
        }
      }

      // By default, show a loading spinner
      return new CircularProgressIndicator();
    },
  ),
);
return vistitCount;
}
}
还更改了如下逻辑,通过此操作,我可以调用REST端点,但小部件数据不是每25秒更新一次。小部件显示的是旧数据

class _MainPageState extends State<MainPage> {
  Future<PatientCount> _patientCount;
  Timer timer;
  @override
  void initState() {
    super.initState();
    //callApi();
    timer = Timer.periodic(Duration(seconds: 15), (Timer t) => callApi());
  }

  void callApi() {
    setState(() {
      _patientCount = fetchPatientCount();
    });
  }

...........................
class\u MainPageState扩展状态{
未来(病人帐);;
定时器;
@凌驾
void initState(){
super.initState();
//callApi();
timer=timer.periodic(持续时间(秒:15),(timer t)=>callApi());
}
void callApi(){
设置状态(){
_patientCount=fetchPatientCount();
});
}
...........................
根据显示相同计数的代码,计数在25秒后不会增加。但是从后端定期触发Api并将数据返回到UI,但小部件的状态没有改变

替换此:

new Timer.periodic(oneSecond, (Timer t) => buildCountWidget());
据此:

new Timer.periodic(oneSecond, (Timer t) => setState((){}));
它应该可以工作,每次调用setState它都会刷新小部件并再次调用Future方法

更新

它工作正常,如果进行这些更改,您将注意到数据是如何刷新的(仅用于测试):

Future fetchPatientCount()异步{
打印(“fetchPatientCount”);
return DateTime.now().toIso8601String();
}
...
新未来建设者(
future:fetchPatientCount(),
生成器:(上下文,快照){
if(snapshot.connectionState==connectionState.done){
if(snapshot.hasData){
/*下面的文字需要每5分钟左右更新一次*/
返回新文本(“#”+snapshot.data.toString(),
样式:TextStyle(
颜色:颜色,黑色,
fontWeight:fontWeight.w700,
体积:7.0),;
}else if(snapshot.hasrerror){
返回新文本(“${snapshot.error}”);
}
}

如果数据每25秒更改一次,那么它就正常工作了,您必须检查
fetchPatientCount
方法。(在发送
requestBody
之前将数据编码为json)

您不需要每次都构建小部件。只需将状态变量设置为文本并更新该变量的状态,它将反映为文本。请详细说明状态变量是什么意思?上述解决方案不起作用,数据不会重新加载,仅显示旧数据。不,我在fetc时没有任何错误处理数据时,端点将返回预期值检查我的更新答案:),如果有效,则获取数据时出错,请不要忘记在发送到http.post之前对requestBody进行编码。请用我的代码替换您的代码,并让我知道它是否有效感谢您的支持,我解决了问题。
new Timer.periodic(oneSecond, (Timer t) => setState((){}));
        Future<String> fetchPatientCount() async {
          print("fetchPatientCount");
          return DateTime.now().toIso8601String();
        }

        ...

        new FutureBuilder<String>(
                future: fetchPatientCount(),
                builder: (context, snapshot) {
                  if (snapshot.connectionState == ConnectionState.done) {
                    if (snapshot.hasData) {            
                      /* below text needs to be updated every 5 mins or so */
                      return new Text('#' + snapshot.data.toString(),
                          style: TextStyle(
                              color: Colors.black,
                              fontWeight: FontWeight.w700,
                              fontSize:7.0));
                    } else if (snapshot.hasError) {
                      return new Text("${snapshot.error}");
                    }
                  }