FLUTTER: How to know if user has quit quit app? - flutter

I want to know when a user shutdown my app and I want to call a function before closing it. I heard about widget binding observer but I don't know if it is the right choice. Do you have documentation or code example about this functionnality ?

You can use this repository and detect when the application is destroyed.
https://pub.dev/packages/flutter_lifecycle_state
class TestRoute extends StatefulWidget {
#override
State<StatefulWidget> createState() => _TestRouteState();
}
class _TestRouteState extends StateWithLifecycle<TestRoute> {
#override
void initState() {
// You need to set the tag id before the super. InitState () method
tagInStateWithLifecycle = "_TestRouteState";
super.initState();
});
#override
void onCreate() {
super.onCreate();
// todo
}
#override
void onResume() {
super.onResume();
// todo
}
#override
void onPause() {
super.onPause();
// todo
}
#override
void onDestroy() {
super.onDestroy();
// todo
}
}

Related

how to get user status (is online) on flutter web

I am working on a flutter web project and want to get the status of the user (online?). I use WidgetsBindingObserver, but didChangeAppLifecycleState doesn't work on the web.
I tried this code.
class HomePage extends StatefulWidget {
const HomePage({super.key});
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>with WidgetsBindingObserver {
#override
void didChangeAppLifecycleState(AppLifecycleState state){
if(state == AppLifecycleState.resumed){
//is online
}else{
//isn't
}
}
#override
void initState() {
// TODO: implement initState
if (kIsWeb) {
window.addEventListener('focus', onFocus);
window.addEventListener('blur', onBlur);
} else {
WidgetsBinding.instance.addObserver(this);
}
super.initState();
}
#override
void dispose() {
if (kIsWeb) {
window.removeEventListener('focus', onFocus);
window.removeEventListener('blur', onBlur);
} else {
WidgetsBinding.instance.removeObserver(this);
}
super.dispose();
}
void onFocus(Event e) {
didChangeAppLifecycleState(AppLifecycleState.resumed);
}
void onBlur(Event e) {
didChangeAppLifecycleState(AppLifecycleState.paused);
}
#override
Widget build(BuildContext context) {
return Scaffold(body: Container(child:Text('hello') ));
}
}
When you focus and blur the web page, it works. The user is still online if you close the tab or browser. To no avail, I tried setting it to outline in the dispose method.

Call a function when user leaves current screen in Flutter [duplicate]

This question already has answers here:
Detect if the user leaves the current page in Flutter?
(6 answers)
Closed 1 year ago.
I want to call a function or get notified when a user leaves the current screen whether he/she navigates back i.e pop the screen or navigate forward in the app.
You need to implement a route observer.
First you need to define an observer :
final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
then you need to add the observer to your material app :
MaterialApp(
navigatorObservers: [routeObserver], ...
Ok. Now when you create a screen, you can add RouteAware to your state. You will need to subscribe to the observer, and dispose it as well. Therefore you need a stateful widget. Let's say you have a screen called MyScreen, it would look like this :
class MyScreen extends StatefulWidget {
#override
_MyScreenState createState() => _MyScreenState();
}
class _MyScreenState extends State<MyScreen> with RouteAware{
#override
void didChangeDependencies() {
routeObserver.subscribe(this, ModalRoute.of(context));
super.didChangeDependencies();
}
#override
void dispose() {
routeObserver.unsubscribe(this);
super.dispose();
} ...
Great! Now you have access to these extra events such as :
#override
void didPopNext() {
super.didPopNext();
}
#override
void didPush() {
super.didPush();
}
#override
void didPushNext() {
super.didPushNext();
}
#override
void didPop() {
super.didPop();
}
Let me know if something was unclear.
you can use dispose() lifecycle function
quote from API
dispose method
Called when this object is removed from the tree permanently.
for example i'm using it to unsubscribe a Timer when user leaves the screen
example:
#override
void dispose() {
super.dispose();
timer.cancel();
}

How to use didChangeAppLifecycleState with Flutter Hooks

I am using Flutter with hooks and I am trying to get the App Life Cycle State. I followed documentation and created new hook (code shown below) which works ok for all situations with one exception. When the application state becomes "paused", the hook does not return the value back to the widget. I am not clear what to do at this point. Someone suggested using Isolates but I don't see how that can help. Updating App Life Cycle is not compute expensive.
Please let me know what else I could do make this work.
Thanks
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
AppLifecycleState useAppLifecycleState() {
return use(const _LifeCycleState());
}
class _LifeCycleState extends Hook<AppLifecycleState> {
const _LifeCycleState();
#override
__LifeCycleState createState() => __LifeCycleState();
}
class __LifeCycleState extends HookState<AppLifecycleState, _LifeCycleState>
with WidgetsBindingObserver {
AppLifecycleState _state;
#override
void initHook() {
super.initHook();
WidgetsBinding.instance.addObserver(this);
}
#override
void dispose() {
super.dispose();
WidgetsBinding.instance.removeObserver(this);
}
#override
AppLifecycleState build(BuildContext context) {
return _state;
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
setState(() {
_state = state;
});
super.didChangeAppLifecycleState(state);
}
}
Thanks for your help.

Abstract class with Change Notifier

I would like to use a Change Notifier with my abstract class but do not think I have this set up correctly. Here is what I am doing:
abstract class Foo with ChangeNotifier {
num get barValue;
}
class FooUtil implements Foo {
num _barNum = 0;
num get barVale => _barNum;
// assume this gets called every 10 seconds.
_someMethod(){
_barNum++;
notifyListeners();
}
}
class Main() {
Foo _foo = FooUtil();
Main() {
_foo.addListener(() {
print(_foo.barValue);
});
}
}
I would like Main to be able to use the listener but this does not seem to work. Am I using the ChangeNotifier wrong in this instance? Is there a method that would work better?
You are missing a few overrides to conform to ChangeNotififier:
#override
void addListener(listener) {
// TODO: implement addListener
}
#override
// TODO: implement barValue
num get barValue => throw UnimplementedError();
#override
void dispose() {
// TODO: implement dispose
}
#override
// TODO: implement hasListeners
bool get hasListeners => throw UnimplementedError();
#override
void notifyListeners() {
// TODO: implement notifyListeners
}
#override
void removeListener(listener) {
// TODO: implement removeListener
}
You will have to implement them before you can use the Class like that.

What is the equivalent of Android LiveData in Flutter?

Android's LiveData allows to update the UI when the activity is in an active state. So if a background operation has finished while the activity is paused, the activity won't be notified and thus the app won't crush. Can Flutter perform the same behavior?
For people interested in an equivalent of LiveData for other scenarios, I present you StreamController:
class ExampleViewModel {
StreamController<bool> loggedInStream = StreamController<bool>();
logIn() { loggedInStream.add(true); }
}
class ExampleScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() => ExampleScreenState();
}
class ExampleScreenState extends State<ExampleScreen> {
ExampleViewModel _viewModel;
BuildContext _ctx;
#override
void initState() {
super.initState();
_viewModel = ExampleViewModel()
_viewModel.loggedInStream.stream.listen( (loggedIn) {
if ( loggedIn != null && loggedIn ) {
Navigator.of(_ctx).pushReplacementNamed("/home");
}
});
}
#override
Widget build(BuildContext context) {
_ctx = context;
var loginBtn =
RaisedButton(
onPressed: _viewModel.logIn(true),
child: Text(
"LOGIN",
style: new TextStyle(
fontSize: 24.0,
)
),
color: Colors.green,
textColor: Colors.white,
);
return loginBtn;
}
#override
void dispose() {
super.dispose();
_viewModel.loggedInStream.close();
}
}
You can subscribe to it just like a LiveData, using:
loggedInStream.stream.listen( (data) { code } )
And you should clear the listeners in dispose to avoid memory leaks:
loggedInStream.close()
This code basically do the following things:
Creates a screen with a button.
Listen to a Stream (observe a LiveData).
When you click the button, it changes the value.
The listener (observer) is triggered.
Launches new screen.
You can use WidgetsBindingObserver to listen to the application state.
class AppLifecycleReactor extends StatefulWidget {
const AppLifecycleReactor({ Key key }) : super(key: key);
#override
_AppLifecycleReactorState createState() => new _AppLifecycleReactorState();
}
class _AppLifecycleReactorState extends State<AppLifecycleReactor> with WidgetsBindingObserver {
#override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
#override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
AppLifecycleState _notification;
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
setState(() { _notification = state; });
}
#override
Widget build(BuildContext context) {
return new Text('Last notification: $_notification');
}
}
Easy: Flutterx Live Data
There is no need to observe App lifecycle: widget are built only when the app is resumend
This library integrates perfectly LiveData concepts, also is well documented.
Is developed on Flutter 1.14.x-dev you need master flutter channel at the moment
Sorry to be late for the party,
My colleague and I have developed a library that mimics the live data of android, on flutter.
Check it out:
https://pub.dev/packages/stream_live_data