Periodically Updating Data

1,728 views
Skip to first unread message

K Wilde

unread,
Jul 22, 2018, 2:52:14 PM7/22/18
to Flutter Dev
I'm fairly new to Flutter and am trying to accomplish the following:

Data is displayed on a page and it's values are updated periodically by reading a web service endpoint with returns a JSON.  I have everything working but can't seem to get my head around how to actually access/update the data after it's been received.  As main.dart shows, 4 items are shown.  I would have thought it would be possible to access the object DataItem directly from my decodeMain method (also attached as part of comms.dart).  I'm scratching my head and would appreciate being pointed in the right direction.  Thanks.

main.dart

import 'package:flutter/material.dart';
import 'dart:async';
import 'comms.dart' as comms;
import 'types.dart' as userTypes;
import 'data_item.dart';
import 'data_item_detail.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget{

@override
Widget build(BuildContext context){
// comms update timer...
new Timer.periodic(new Duration(seconds:5), comms.doUpdate);
return new MaterialApp(
title: 'Mobile Data',
theme: new ThemeData(
primarySwatch: Colors.blue
),
home: new MainPage(title:"Main Window"),
routes: <String,WidgetBuilder>{
'/data_item_detail':(BuildContext context) => new DataItemDetail(),
}
);
}
}

class MainPage extends StatefulWidget{
final String title;
MainPage({Key key, this.title}) : super(key: key);

@override
_MainPageState createState() => new _MainPageState();

}

class _MainPageState extends State<MainPage>{
@override
Widget build(BuildContext context){
// declare tags..

var tags = []
..add(new userTypes.Tag('[MobileTest]Main Pump/Pressure','Main Pump Pressure',0.0,'PSI',false))
..add(new userTypes.Tag('[MobileTest]Main Pump/Rate','Main Pump Rate',0.0,'PSI',false))
..add(new userTypes.Tag('[MobileTest]Booster Pump/Pressure','Booster Pump Pressure',0.0,'GPM',false))
..add(new userTypes.Tag('[MobileTest]Booster Pump/Rate','Booster Pump Rate',0.0,'GPM',false));



return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
backgroundColor: Colors.blue,
),
body: new Padding(
padding: new EdgeInsets.all(20.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new DataItem(tag:tags[0],color:Colors.blueAccent),
new DataItem(tag:tags[1],color:Colors.blueAccent),
new DataItem(tag:tags[2],color:Colors.blueAccent),
new DataItem(tag:tags[3],color:Colors.blueAccent),
],
)
)
);
}

}

comms.dart

// All things communications related....

library list_view_app.comms;

import 'globals.dart' as globals;
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'main.dart' as MainPage;



final String _mainURL = 'http://192.168.1.102:8088/main/system/webdev/FlutterMobileTest/main';

doUpdate(Timer t){
globals.updateCount += 1;
print("Timed event updateCount = " + globals.updateCount.toString());
getMain();
}

getMain() async{
// get data for main window...
String url = Uri.encodeFull(_mainURL);
//print(url);
var response = await http.get(url,headers:{"Accept":"application.json"});

Map<String,dynamic> data = json.decode(response.body);
//print(data);
decodeMain(data['data']);

}


decodeMain(tagList){
for (var i = 0; i < tagList.length; i++){
// Map<String,dynamic> tag = json.decode(tagList[i]);
print(tagList[i]['tagPath'] + " = " + tagList[i]["value"].toString());

}
} 

Dale King

unread,
Jul 22, 2018, 6:37:05 PM7/22/18
to Flutter Dev
Flutter handles state differently than many other frameworks. Widgets at the lowest level are stateless and immutable. Stateful widgets are just wrappers that rebuild new widgets based on changes to state. To update the UI you need something that is going to call setState on the stateful widget to tell it to rebuild it UI. That call cannot come from the asynchronous code due to the thread, but there are other ways that actually end up calling a setState to update the UI.

One simple way to accomplish it is to use a StreamController for holding the current set of values. The UI piece can use a StreamBuilder that subscribes to changes in the stream and rebuilds. The background task then just pushes new values into the stream.

The better, more complete way to architect the solution is to use redux (https://blog.novoda.com/introduction-to-redux-in-flutter/). In redux, you might have a refresh data action that is periodically dispatched to the redux Store. That action would be handled by Middleware that does the load from the server and when the data is received it would dispatch another action containing the data received. This new data action is caught by the reducer which updates the state in the Store that then triggers a StoreBuilder listening for store changes to rebuild the UI.
Reply all
Reply to author
Forward
0 new messages