DEV Community

Nav
Nav

Posted on

Is the use of StatelessWidget with Provider a reliable way to achieve background runs in Flutter?

I asked this question on StackOverflow, but it got closed as an opinion based question. I intend to build an app which I'd be making available on Google Playstore, so I need to know from the Flutter developers, whether the use of StatelessWidget and Provider are an acceptable and reliable way of ensuring that my timers run in the background and when the phone screen is locked.
If this is considered "bad engineering", please mention it, and also do provide a working method of ensuring that the timers don't pause when the screen is locked or when the User switches to another app.
If the Flutter developers see this technique as not being good and you later make changes in Flutter to disallow this, I'll be left in the lurch. So I'd like to know now itself, whether this is an acceptable and reliable way of programming what I want.

The code which works:
`import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'dart:async';

class TimerProvider with ChangeNotifier {
List _timers = [];
List _timerInstances = [];
List get timers => _timers;

void addTimer(int duration) {_timers.add(duration); _startTimer(_timers.length - 1); notifyListeners();}
void decrementTimer(int index) {if (_timers[index] > 0) {_timers[index]--; notifyListeners();}}

void _startTimer(int index) {
if (_timerInstances.length <= index || _timerInstances[index] == null) {_timerInstances.add(null);
_timerInstances[index] = Timer.periodic(Duration(seconds: 1), (timer) {decrementTimer(index);
if (_timers[index] <= 0) {timer.cancel();_timerInstances[index] = null;}
});
}
}

}

class TimerScreen extends StatelessWidget {
final int index;
TimerScreen({required this.index});

@override
Widget build(BuildContext context) {
final timerProvider = Provider.of(context);
return Scaffold(appBar: AppBar(title: Text('Timer ${index + 1}')),
body: Center(child: Text('Time Remaining: ${timerProvider.timers[index]} seconds', style: TextStyle(fontSize: 30),),),
);
}
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(create: (_) => TimerProvider(), child: MaterialApp(title: 'Countdown Timer', theme: ThemeData.dark(), home: HomeScreen(),),);
}
}

class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Countdown Timers')),
body: Consumer(
builder: (context, timerProvider, child) {
return ListView.builder(itemCount: timerProvider.timers.length,
itemBuilder: (context, index) {
return Card(child: ListTile(title: Text('Timer ${index + 1}'), subtitle: Text('Time Remaining: ${timerProvider.timers[index]} seconds'),
onTap: () {Navigator.push(context, MaterialPageRoute(builder: (context) => TimerScreen(index: index),),);},
),
);
},
);
},
),
floatingActionButton: FloatingActionButton(onPressed: () {Provider.of(context, listen: false).addTimer(60);}, child: Icon(Icons.add),),
);
}
}

void main() {runApp(MyApp());}`

Top comments (0)