This little invisible Custom Widget does an automatic refresh of the page it is placed on. You can specify the number of seconds before the refresh. The refresh includes running any API calls or queries. You can also easily change this widget to be an automatic logout after a time interval. Please see below.
I place it in the AppBar where the back button normally resides (because obviously a page that auto-refreshes cannot have a back option) and give it a width and height of 10 each:
The parameters are as follows:
And here is the code:
import 'dart:async';
import 'package:after_layout/after_layout.dart';
class RefreshWidget extends StatefulWidget {
const RefreshWidget({
Key key,
this.width,
this.height,
this.interval,
}) : super(key: key);
final double width;
final double height;
final int interval;
@override
_RefreshWidgetState createState() => _RefreshWidgetState();
}
class _RefreshWidgetState extends State<RefreshWidget>
with AfterLayoutMixin<RefreshWidget> {
Timer _timer;
int _start;
void startTimer(int interval) {
_start = interval;
const oneSec = const Duration(seconds: 1);
_timer = new Timer.periodic(
oneSec,
(Timer timer) {
if (_start == 0) {
timer.cancel();
// Navigate to ourselves
Navigator.pushReplacementNamed(
context, ModalRoute.of(context).settings.name);
} else {
_start--;
}
},
);
}
void stopTimer() {
_timer.cancel();
}
@override
void afterFirstLayout(BuildContext context) {
int interval = widget.interval;
// For safety
if (interval == 0 || interval == null) interval = 100;
// Start the timer
startTimer(interval);
}
@override
void dispose() {
_timer.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
width: 10,
height: 10,
decoration: BoxDecoration(color: Color(0x00000000)),
);
}
}
To make it an auto-logout Widget instead (assuming your home page is the login page), simply replace the navigation with:
Navigator.pushReplacementNamed(context, "/");
For auto-logout, you may need to place the widget in a Stack somewhere. It is fully transparent and no more than 10 pixels wide, so on top of any text widget will do the trick.
Edit: As I worked on a Splash Screen version of this, I came to the realization that this Widget would only work for the home page. That is because FF does not actually use named routes, but rather the simpler object routes.
However, after a bit of messing around, I found a work-around. It does come with a quirk (I will explain after the solution):
So to make this work on any given page, you need copy the code above and add the import of the page you wish to refresh/logout/after-splash at the top. In my case I have a page called TestSplash, so I import:
import '../../test_splash/test_splash_widget.dart';
And then change the navigation from:
Navigator.pushReplacementNamed(
context, ModalRoute.of(context).settings.name);
to:
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => TestSplashWidget(),
));
Now, here is the quirk. This will NOT compile and preview. You will forever have a message like this:
BUT, you can simply ignore it. It happens because the Custom Widget is compiled out of context. It cannot see the other Widgets in the project. However, at runtime this is not a problem and the FlutterFlow team mercifully enough allows us to run a project even though it has the error shown above.