Flutter:检测API中的更改

时间:2019-01-11 02:26:55

标签: dart flutter

我目前有一个简单的API,但是我的flutter小部件在不重新启动整个应用程序的情况下无法检测到API中发生的更改。

该API是在https://www.mockable.io/上作为测试API制成的。我设法使用StreamBuilder从该API读取了内容。而且无论何时更新API中的值,它都不会更改小部件中的值。

默认JSON

{
 "id": "123",
 "token": "1token",
 "status": "Valid"
}

价值变更后

{
 "id": "123",
 "token": "1token",
 "status": "Not Valid"
}

我的StreamBuilder代码

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;

final String url = "http://demo2722084.mockable.io/user";

class StreamPage extends StatefulWidget {

  @override
  StreamPageState createState() {
    return new StreamPageState();
  }
}

class StreamPageState extends State<StreamPage> {

  StreamController _userController;

  Future fetchUser() async{
    final response = await http.get(url);

    if(response.statusCode == 200){
      return json.decode(response.body);
    }else{
      print("Exception caught: Failed to get data");
    }
  }

  loadUser() async{
    fetchUser().then((res) async{
      _userController.add(res);
      return res;
    });
  }

  @override
  void initState() {
    _userController = new StreamController();
    loadUser();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {

    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Stream"),
      ),
      body: new StreamBuilder(
        stream: _userController.stream,
        builder: (context, snapshot){

          if(snapshot.hasError){
            print("Exception: ${snapshot.error}");
          }

          if(snapshot.hasData){

            var user = snapshot.data;

            var id = user["id"] ?? "";
            var token = user["token"] ?? "";
            var status = user["status"] ?? "";

            return new Center(
              child: new ListTile(
                title: new Text("Token: $token"),
                subtitle: new Text("Status: $status"),
                leading: new Text(id),
              ),
            );
          }

          if(snapshot.connectionState != ConnectionState.waiting){
            return new Center(
              child: new CircularProgressIndicator(),
            );
          }

          if(!snapshot.hasData && snapshot.connectionState != ConnectionState.done){
            return new Center(
              child: new CircularProgressIndicator(),
            );
          }
        },
      ),
    );
  }
}

我希望StreamBuilder能够获取更改后的状态值,但是必须重新启动该应用程序才能使新值反映在应用程序中。

是否有一个示例,说明如何正确实现此目标,因为坦率地说,这是我第一次尝试StreamBuilder。

2 个答案:

答案 0 :(得分:1)

您的HTTP请求仅产生一个数据点,因此您可以使用FutureBuilder。但是您想知道服务器上什么时候发生更改。进行更改后,您的HTTP连接已完成,因此不知道它已发生。

有多种方法可以检测服务器上的更改,例如,轮询,用户启动的刷新,WebSocket等。出于演示目的,您可以启动一个A,而不是在loadUser中调用initState 1秒的定期计时器可以做到这一点,它将每秒更新一次流,您应该会看到更改。 (不要忘记取消dispose中的计时器。)

这在生产中不太可行,因此请探索websockets等,以获取来自Web服务器的推送通知。还应探索Firebase Cloud Messaging是否是将更改通知发送到您的应用程序的更好方法。

  @override
  void initState() {
    super.initState();
    _userController = StreamController();
    Timer.periodic(Duration(seconds: 1), (_) => loadUser());
  }

答案 1 :(得分:0)

您可能还需要仅在应用程序处于前台状态时执行此操作。您可以使用我的LifecycleAwareStreamBuilder,其中有一个有关如何使用它的示例here