-
Notifications
You must be signed in to change notification settings - Fork 162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[mounted value becomes false inside _onBackgroundFetch callback. Due to this i am unable to run setState(() {}). ] #42
Comments
The |
Show me more context of where you've placed |
BackgroundFetch.configure is placed in my homepage.dart <<<<<<main.dart>>>>>>>>>>> import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:zoomme_mobile/pages/loginpage.dart';
import 'package:zoomme_mobile/pages/homepage.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:background_fetch/background_fetch.dart';
/// This "Headless Task" is run when app is terminated.
void backgroundFetchHeadlessTask() async {
print('[BackgroundFetch] Headless event received.');
print('@@@@@@ PREMA headless Fetch');
SharedPreferences prefs = await SharedPreferences.getInstance();
// Read fetch_events from SharedPreferences
List<String> events = [];
String json = prefs.getString(EVENTS_KEY);
if (json != null) {
events = jsonDecode(json).cast<String>();
}
// Add new event.
events.insert(0, new DateTime.now().toString() + ' [Headless]');
// Persist fetch events in SharedPreferences
prefs.setString(EVENTS_KEY, jsonEncode(events));
BackgroundFetch.finish();
}
void main() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var token = prefs.getString('LastToken');
//run app
runApp(new MaterialApp(
title: 'Demo',
theme: buildTheme(),
home: token == null ? LoginPage() : HomePage(),
routes: <String, WidgetBuilder> {
//set routes for using the navigator
'/home': (BuildContext context) => new HomePage(),
'/login': (BuildContext context) => new LoginPage(),
},
));
BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
} ==================================================================== class LoginPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => new _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final emailController = TextEditingController();
final passwordController = TextEditingController();
@override
void initState() {
super.initState();
saveCurrentRoute("/login");
}
@override
Widget build(BuildContext context) {
final emailField = TextField(
obscureText: false,
style: style,
controller: emailController,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
hintText: "Email",
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0))
),
);
final passwordField = TextField(
obscureText: true,
style: style,
controller: passwordController,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
hintText: "Password",
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0))),
);
final loginButon = Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(30.0),
color: Colors.redAccent,
child: MaterialButton(
minWidth: MediaQuery.of(context)
.size
.width,
padding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
onPressed: () async {
await loginAPI(context, emailController.text, passwordController.text).then((ConfigModel loginStatus) {
if(loginStatus != null) {
_isLoading = false;
print('POST login passed');
Navigator.of(context).pushReplacementNamed('/home');
return loginStatus.authToken;
} else {
setState(() {
_isLoading = false;
emailController.text = '';
passwordController.text = '';
});
print('POST login failled');
return null;
}
});
},
),
);
return Scaffold(
body: SingleChildScrollView(
child: Center(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(36.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 155.0),
SizedBox(height: 45.0),
emailField,
SizedBox(height: 25.0),
passwordField,
SizedBox(
height: 35.0,
),
loginButon,
SizedBox(
height: 15.0,
),
],
),
),
),
),
),
);
}
} ============================================================================ const EVENTS_KEY = "fetch_events";
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Geolocator geoLocator = Geolocator();
var loginUserName = '';
int _status = 0;
List<String> _events = [];
@override
void initState() {
super.initState();
saveCurrentRoute("/home");
getSharedPreference();
initPlatformState();
}
getSharedPreference() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
loginUserName = preferences.getString('LoginUserName');
setState(() {
});
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
// Load persisted fetch events from SharedPreferences
SharedPreferences prefs = await SharedPreferences.getInstance();
String json = prefs.getString(EVENTS_KEY);
if (json != null) {
setState(() {
_events = jsonDecode(json).cast<String>();
});
}
// Configure BackgroundFetch.
BackgroundFetch.configure(BackgroundFetchConfig(
minimumFetchInterval: 15,
stopOnTerminate: false,
enableHeadless: true,
forceReload: false
), _onBackgroundFetch).then((int status) {
print('[BackgroundFetch] SUCCESS: $status');
setState(() {
_status = status;
});
}).catchError((e) {
print('[BackgroundFetch] ERROR: $e');
setState(() {
_status = e;
});
});
// Optionally query the current BackgroundFetch status.
int status = await BackgroundFetch.status;
setState(() {
_status = status;
});
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
}
void _onBackgroundFetch() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
print('[BackgroundFetch] Event received');
if(true) {
//this setState throws error. Mounted value false
setState(() {
print('set state PASS');
});
}
BackgroundFetch.finish();
}
@override
Widget build(BuildContext context) => new Scaffold(
appBar: new AppBar(
backgroundColor: Colors.red,
title: new Text('Hi $loginUserName, '),
actions: <Widget>[
new FlatButton.icon(
),
],
),
drawer: BasicDrawer(),
body: new Card(
child: new Column(
children: <Widget>[
ListTile(
title: Text(''),
),
ListTile(
title: Text(''),
)
],
),
),
);
} |
okay. Will follow. |
Please make a simple test-case app that reproduces the problem and share that Github repo with me. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. You may also mark this issue as a "discussion" and I will leave this open. |
Closing this issue after a prolonged period of inactivity. Fell free to reopen this issue, if this still affecting you. |
Your Environment
flutter info
,flutter doctor
):Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.7.8+hotfix.4, on Linux, locale en_IN)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
[✓] Android Studio (version 3.4)
[!] VS Code (version 1.34.0)
✗ Flutter extension not installed; install from
https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[✓] Connected device (1 available)
To Reproduce
Steps to reproduce the behavior:
Calling setState((){}); throws below error when setState() called from BackgroundFetch callback
Debug logs
D/TSBackgroundFetch( 6511): - configure: {
D/TSBackgroundFetch( 6511): "minimumFetchInterval": 15,
D/TSBackgroundFetch( 6511): "stopOnTerminate": false,
D/TSBackgroundFetch( 6511): "startOnBoot": false,
D/TSBackgroundFetch( 6511): "forceReload": false,
D/TSBackgroundFetch( 6511): "jobService": "com.transistorsoft.flutter.backgroundfetch.HeadlessJobService"
D/TSBackgroundFetch( 6511): }
D/TSBackgroundFetch( 6511): - start
I/flutter ( 6511): [BackgroundFetch] SUCCESS: 2
D/TSBackgroundFetch( 6511): - Background Fetch event received
I/flutter ( 6511): [BackgroundFetch] Event received
E/flutter ( 6511): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: setState() called after dispose(): _HomePageState#53dc8(lifecycle state: defunct, not mounted)
E/flutter ( 6511): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
E/flutter ( 6511): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
E/flutter ( 6511): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
E/flutter ( 6511): #0 State.setState. (package:flutter/src/widgets/framework.dart:1105:9)
E/flutter ( 6511): #1 State.setState (package:flutter/src/widgets/framework.dart:1140:6)
E/flutter ( 6511): #2 _HomePageState.initPlatformState. (package:demo_mobile/pages/homepage.dart:85:7)
E/flutter ( 6511):
E/flutter ( 6511): #3 BackgroundFetch.configure. (package:background_fetch/background_fetch.dart:169:17)
E/flutter ( 6511): #4 _rootRunUnary (dart:async/zone.dart:1132:38)
E/flutter ( 6511): #5 _CustomZone.runUnary (dart:async/zone.dart:1029:19)
E/flutter ( 6511): #6 _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7)
E/flutter ( 6511): #7 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11)
E/flutter ( 6511): #8 _DelayedData.perform (dart:async/stream_impl.dart:591:14)
E/flutter ( 6511): #9 _StreamImplEvents.handleNext (dart:async/stream_impl.dart:707:11)
E/flutter ( 6511): #10 _PendingEvents.schedule. (dart:async/stream_impl.dart:667:7)
E/flutter ( 6511): #11 _rootRun (dart:async/zone.dart:1120:38)
E/flutter ( 6511): #12 _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter ( 6511): #13 _CustomZone.runGuarded (dart:async/zone.dart:923:7)
E/flutter ( 6511): #14 _CustomZone.bindCallbackGuarded. (dart:async/zone.dart:963:23)
E/flutter ( 6511): #15 _rootRun (dart:async/zone.dart:1124:13)
E/flutter ( 6511): #16 _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter ( 6511): #17 _CustomZone.runGuarded (dart:async/zone.dart:923:7)
E/flutter ( 6511): #18 _CustomZone.bindCallbackGuarded. (dart:async/zone.dart:963:23)
E/flutter ( 6511): #19 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter ( 6511): #20 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
E/flutter ( 6511):
Additional context
Add any other context about the problem here.
The text was updated successfully, but these errors were encountered: