每5分钟或定期刷新Flutter Text小部件内容

时间:2018-12-25 04:41:50

标签: dart flutter flutter-animation

我有一个Flutter 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;
}
}

buildCountWidget方法中,文本小部件需要用网络中的最新数据刷新。

我将实现更改为使用setState,如下所示,仍然没有运气

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

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

还更改了逻辑,如下所示,我可以调用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();
    });
  }

...........................

根据代码显示相同的计数,计数在25秒后不会增加,但是从后端定期触发Api并将数据返回到UI,但窗口小部件的状态没有改变。

here the count is not changing every 25 seconds

1 个答案:

答案 0 :(得分:0)

替换此:

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

通过这个:

new Timer.periodic(oneSecond, (Timer t) => setState((){}));

它应该工作,每次调用setState时,它将刷新小部件并再次调用Future方法。

更新

一切正常,如果进行这些更改,您会注意到如何刷新数据(仅用于测试):

        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}");
                    }
                  }

如果数据每25秒更改一次,则表明该数据正常运行,您必须检查fetchPatientCount方法。 (在发送requestBody之前将数据编码为json)