Related
Good day! I am new to Flutter/Dart. And the more I experiment, the bigger my main file gets. Obviously, I need a separate file in which I will store all the classes and functions that I will refer to in the future.
I have a separate screen with what I need. Here is its code:
//Internet route
class InternetRoute extends StatefulWidget {
const InternetRoute({Key? key}) : super(key: key);
#override
State<InternetRoute> createState() => _InternetRouteState();
}
class _InternetRouteState extends State<InternetRoute> {
bool ActiveConnection = false;
String T = "";
Future CheckUserConnection() async {
try {
final result = await InternetAddress.lookup('example.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
setState(() {
ActiveConnection = true;
T = "Turn off the data and repress again";
});
}
} on SocketException catch (_) {
setState(() {
ActiveConnection = false;
T = "Turn On the data and repress again";
showInternetDialog(context);
});
}
}
#override
void initState() {
CheckUserConnection();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("GeeksforGeeks"),
),
body: Column(
children: [
Text("Active Connection? $ActiveConnection"),
const Divider(),
Text(T),
OutlinedButton(
onPressed: () {
CheckUserConnection();
},
child: const Text("Check"))
],
),
);
}
}
//Alert Dialog about Internet connection
showInternetDialog(BuildContext context) {
// set up the button
Widget okButton = Center(
child: TextButton(
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop(); // dismiss dialog
},
),
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
// title: Text("My title"),
content: Text("Internet connection required"),
actions: [
okButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
I want to create a my classes.dart file that will gradually populate with the most commonly used things. In particular, I need class _InternetRouteState and showInternetDialog.
How to transfer them to a new file? I completely copied the code of that screen. Is it correct? Would that be enough to then refer to them in main.dart (after import)? Will all their variables be visible to my screens as well?
Edit 1. I don't know how I can move CheckUserConnection to my file. I mean I took the piece of code I needed and wrapped it in the CheckUserConnection class (in my separate file), but it doesn't work. What am I doing wrong?
class CheckUserConnection {
bool ActiveConnection = false;
String T = "";
Future CheckUserConnection() async {
try {
final result = await InternetAddress.lookup('example.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
setState(() {
ActiveConnection = true;
T = "Turn off the data and repress again";
});
}
} on SocketException catch (_) {
setState(() {
ActiveConnection = false;
T = "Turn On the data and repress again";
// showInternetDialog(context); //temporary
});
}
}
}
The Problems tab shows the following errors:
Constructors can't have a return type.
The modifier 'async' can't be applied to the body of a constructor.
The await expression can only be used in an async function.
The method 'setState' isn't defined for the type 'CheckUserConnection'.
The method 'setState' isn't defined for the type 'CheckUserConnection'.
Create a new dart file. Name it internet_dialog_handler.dart. Add this to the file
class InternetDialogHandler{
//Alert Dialog about Internet connection
showInternetDialog(BuildContext context) {
// set up the button
Widget okButton = Center(
child: TextButton(
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop(); // dismiss dialog
},
),
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
// title: Text("My title"),
content: Text("Internet connection required"),
actions: [
okButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
In internetRoute use this
//Internet route
class InternetRoute extends StatefulWidget {
const InternetRoute({Key? key}) : super(key: key);
#override
State<InternetRoute> createState() => _InternetRouteState();
}
class _InternetRouteState extends State<InternetRoute> {
bool ActiveConnection = false;
String T = "";
InternetDialogHandler _internetDialogHandler = InternetDialogHandler();
Future CheckUserConnection() async {
try {
final result = await InternetAddress.lookup('example.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
setState(() {
ActiveConnection = true;
T = "Turn off the data and repress again";
});
}
} on SocketException catch (_) {
setState(() {
ActiveConnection = false;
T = "Turn On the data and repress again";
//Use the variable here to access the method in that class
_internetDialogHandler.showInternetDialog(context);
});
}
}
#override
void initState() {
CheckUserConnection();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("GeeksforGeeks"),
),
body: Column(
children: [
Text("Active Connection? $ActiveConnection"),
const Divider(),
Text(T),
OutlinedButton(
onPressed: () {
CheckUserConnection();
},
child: const Text("Check"))
],
),
);
}
}
EDIT
class CheckUserConnection {
Future checkInternetAvailability() async {
try {
final result = await InternetAddress.lookup('example.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
return true;
}
} on SocketException catch (_) {
return false;
}
}
}
Use a different name for the method. Same name is used to defined the constructor of the class. Also make it work independent. Just return a true or false. Now to use this define a variable of type checkUserConnection
CheckUserConnection _checkUserConnection = CheckUserConnection();
bool _internetAvailable = await _checkUserConnection.checkInternetAvailability();
if(_internetAvailable)
{
//do something here;
} else{
//handle no internet here
}
I am trying to ask location permission of user in my project apps, so after user denied the permission I would like to keep showing pop up to ask location permission whenever user try to access a menu. I success to do that by using this function
trial() async {
await Permission.locationAlways.request();
print(Permission.locationAlways.status.then((value) {
print("value:$value");
}));
}
but the problem is.. after the status is PermissionStatus.permanentlyDenied the pop up to ask location permission is stop showing. Is there a way to always ask permission as long as the permission is not granted or a way to open up setting of location permission?
you can use the permission_handler 8.3.0 package.
and use as:
if (await Permission.locationAlways.request().isGranted) {
print(Permission.locationAlways.status.then((value) {
print("value:$value");
}));
}
more details on: permission_handler
implementation on: implementation on
Please refer to below code
class MyApp extends StatelessWidget {
MyApp({Key key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primaryColor: Color(0xfff00B074),
textTheme: const TextTheme(
bodyText1: TextStyle(
fontSize: 18.0,
fontFamily: 'Barlow-Medium',
color: Color(0xff464255)),
),
),
home: PermissionHandlerScreen(),
);
}
}
class PermissionHandlerScreen extends StatefulWidget {
#override
_PermissionHandlerScreenState createState() =>
_PermissionHandlerScreenState();
}
class _PermissionHandlerScreenState extends State<PermissionHandlerScreen> {
#override
void initState() {
super.initState();
permissionServiceCall();
}
permissionServiceCall() async {
await permissionServices().then(
(value) {
if (value != null) {
if (value[Permission.location].isGranted ) {
/* ========= New Screen Added ============= */
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => SplashScreen()),
);
}
}
},
);
}
/*Permission services*/
Future<Map<Permission, PermissionStatus>> permissionServices() async {
// You can request multiple permissions at once.
Map<Permission, PermissionStatus> statuses = await [
Permission.location,
//add more permission to request here.
].request();
if (statuses[Permission.location].isPermanentlyDenied) {
await openAppSettings().then(
(value) async {
if (value) {
if (await Permission.location.status.isPermanentlyDenied == true &&
await Permission.location.status.isGranted == false) {
// openAppSettings();
permissionServiceCall(); /* opens app settings until permission is granted */
}
}
},
);
} else {
if (statuses[Permission.location].isDenied) {
permissionServiceCall();
}
}
/*{Permission.camera: PermissionStatus.granted, Permission.storage: PermissionStatus.granted}*/
return statuses;
}
#override
Widget build(BuildContext context) {
permissionServiceCall();
return WillPopScope(
onWillPop: () {
SystemNavigator.pop();
},
child: Scaffold(
body: Container(
child: Center(
child: InkWell(
onTap: () {
permissionServiceCall();
},
child: Text("Click here to enable Enable Permission Screen")),
),
),
),
);
}
}
class SplashScreen extends StatelessWidget {
const SplashScreen({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
SystemNavigator.pop();
},
child: Scaffold(
body: Center(
child: Text(
"Splash Screen",
),
),
),
);
}
}
I dont know how to resolve this red error part.
I copied this from internet then i got this error.
please help me to solve this.
This is my full code.
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:android_intent/android_intent.dart';
import 'package:geolocator/geolocator.dart';
class AskForPermission extends StatefulWidget {
#override
_AskForPermissionState createState() => _AskForPermissionState();
}
class _AskForPermissionState extends State<AskForPermission> {
final PermissionHandler permissionHandler = PermissionHandler();
Map<PermissionGroup, PermissionStatus>? permissions;
void initState() {
super.initState();
requestLocationPermission();
_gpsService();
}
Future<bool> _requestPermission(PermissionGroup permission) async {
final PermissionHandler _permissionHandler = PermissionHandler();
var result = await _permissionHandler.requestPermissions([permission]);
if (result[permission] == PermissionStatus.granted) {
return true;
}
return false;
}
/*Checking if your App has been Given Permission*/
Future<bool> requestLocationPermission({Function? onPermissionDenied}) async {
var granted = await _requestPermission(PermissionGroup.location);
if (granted!=true) {
requestLocationPermission();
}
debugPrint('requestContactsPermission $granted');
return granted;
}
/*Show dialog if GPS not enabled and open settings location*/
Future _checkGps() async {
if (!(await Geolocator.isLocationServiceEnabled())) {
if (Theme.of(context).platform == TargetPlatform.android) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Can't get gurrent location"),
content:const Text('Please make sure you enable GPS and try again'),
actions: <Widget>[
FlatButton(child: Text('Ok'),
onPressed: () {
final AndroidIntent intent = AndroidIntent(
action: 'android.settings.LOCATION_SOURCE_SETTINGS');
intent.launch();
Navigator.of(context, rootNavigator: true).pop();
_gpsService();
})],
);
});
}
}
}
/*Check if gps service is enabled or not*/
Future _gpsService() async {
if (!(await Geolocator.isLocationServiceEnabled())) {
_checkGps();
return null;
} else
return true;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ask for permisions'),
backgroundColor: Colors.red,
),
body: Center(
child: Column(
children: <Widget>[
Text("All Permission Granted"),
],
))
);
}
}
I got the same problem - the code that worked with permission_handler ^8.0.0+2 didn't work anymore after I upgraded to ^8.3.0 - the code wouldn't compile, the Permission and the other classes where not "found" anymore (I use VS Code)
I fixed it by cleaning the pub cache:
flutter pub cache clean
and afterwards just get again the dependencies:
flutter pub get
PS: for upgrading to 8.3.0, I set targetSdkVersion and compileSdkVersion to 31 into build.gradle file
Install permission handler package from here. Then in your .dart file add import and call permission asking function somewhere. E.g. function like this asks for storage permission.
import 'package:permission_handler/permission_handler.dart';
Future<void> getStoragePermission() async {
if (await Permission.manageExternalStorage.request().isGranted) {
setState(() {});
} else if (await Permission.storage.request().isPermanentlyDenied) {
await openAppSettings();
} else if (await Permission.storage.request().isDenied) {
setState(() {});
}
}
Please refer to below code
https://pub.dev/packages/permission_handler/install
permission_handler: ^5.0.1+1
import 'package:permission_handler/permission_handler.dart';
import 'package:google_fonts/google_fonts.dart';
class MyApp extends StatelessWidget {
MyApp({Key key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primaryColor: Color(0xfff00B074),
textTheme: const TextTheme(
bodyText1: TextStyle(
fontSize: 18.0,
fontFamily: 'Barlow-Medium',
color: Color(0xff464255)),
),
),
home: PermissionHandlerScreen(),
);
}
}
class PermissionHandlerScreen extends StatefulWidget {
#override
_PermissionHandlerScreenState createState() =>
_PermissionHandlerScreenState();
}
class _PermissionHandlerScreenState extends State<PermissionHandlerScreen> {
#override
void initState() {
super.initState();
permissionServiceCall();
}
permissionServiceCall() async {
await permissionServices().then(
(value) {
if (value != null) {
if (value[Permission.storage].isGranted &&
value[Permission.camera].isGranted &&
value[Permission.microphone].isGranted) {
/* ========= New Screen Added ============= */
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => SplashScreen()),
);
}
}
},
);
}
/*Permission services*/
Future<Map<Permission, PermissionStatus>> permissionServices() async {
// You can request multiple permissions at once.
Map<Permission, PermissionStatus> statuses = await [
Permission.storage,
Permission.camera,
Permission.microphone,
//add more permission to request here.
].request();
if (statuses[Permission.storage].isPermanentlyDenied) {
openAppSettings();
setState(() {});
} else {
if (statuses[Permission.storage].isDenied) {
permissionServiceCall();
}
}
if (statuses[Permission.microphone].isPermanentlyDenied) {
openAppSettings();
setState(() {});
} else {
if (statuses[Permission.microphone].isDenied) {
permissionServiceCall();
}
}
if (statuses[Permission.camera].isPermanentlyDenied) {
openAppSettings();
setState(() {});
} else {
if (statuses[Permission.camera].isDenied) {
permissionServiceCall();
}
}
/*{Permission.camera: PermissionStatus.granted, Permission.storage: PermissionStatus.granted}*/
return statuses;
}
#override
Widget build(BuildContext context) {
permissionServiceCall();
return WillPopScope(
onWillPop: () {
SystemNavigator.pop();
},
child: Scaffold(
body: Container(
child: Center(
child: InkWell(
onTap: () {
permissionServiceCall();
},
child: Text("Click here to enable Enable Permission Screen")),
),
),
),
);
}
}
class SplashScreen extends StatelessWidget {
const SplashScreen({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
SystemNavigator.pop();
},
child: Scaffold(
body: Center(
child: Text(
"Splash Screen",
),
),
),
);
}
}
Add permission_handler dependency in your pubspec.yaml file.
Try the flutter pub get command. If already done, then refer to this link about the permission handler package.
Sorry!! The question may be duplicate but I'm unable to found the solution. Here is my problem
I Completed my flutter app and Almost Everything works fine but there is one problem. I close The app using the Device Back Button and when I open it again first White Screen opens and after some second Black Screen opens and stay on That black Screen (stuck on black Screen) app Crashes
Here is Everything you need.
My Folder Structure is, user SIGNUP() or login(), I have a login and signup page(), from the login or signup page when the user presses the login or signup button he Goes to HomeControllerpage() page
HomeControllerPage() is a page that Authenticates the user and Redirects to homePage() if the user is Authenticated. otherwise, the user Redirects to the login/signup page again if he or she is not authenticated
Here is my Main.dart
void main()async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp().catchError((e) {
print(e);
});
runApp(
Myapp());
}
class Myapp extends StatefulWidget {
#override
State<Myapp> createState() => _MyappState();
}
class _MyappState extends State<Myapp> {
#override
Widget build(BuildContext context) {
return Provider(
auth: Authservice(),
child: MaterialApp(
title: 'signup',
theme: ThemeData(
primarySwatch: Colors.green,
),
initialRoute: '/home',
debugShowCheckedModeBanner: false,
//flutter home:email==null? homecontroller(controllUserType: 'hfdd',):null,
routes: <String,WidgetBuilder>{
'/home':(BuildContext context)=>homecontroller(),
'/Signup':(BuildContext context)=>signup_view(authFormType: AuthFormType.Signup,),
'/SignIn':(BuildContext context)=>signup_view(authFormType: AuthFormType.SignIn,),
'/dropDown':(BuildContext context)=>dropDown()//delet this
},
),
);
}
}
Here is how the user Signup, Signup() page
Future<String> CreateUserUisngEmailAndPassword(
BuildContext context,
String _firstname,
String _userID,
String _dropDownValue,
) async {
try {
final UserCredential Newuser = await _firebaseAuth
.createUserWithEmailAndPassword(email: email, password: _password);
User curentRegistereduser = Newuser.user;
await AddToDataBase(uid: curentRegistereduser.uid).firebaseuserdata(
_firstname,
_userID=curentRegistereduser.uid,
);
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context)=>homecontroller(
controllUserType:_dropDownValue,
userid:_userID,
)));
}on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
}
} catch (e) {
print(e);
}
//Update User
}
Here is How user Login. / Loginpage()
Future loginWithEmailAndPasswords(String email, String password,BuildContext context) async {
try {
UserCredential register = await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
User registredUser = register.user;
final ownerSnapshots= await ownerReference.doc(registredUser.uid).get();
final userSnapshots= await userSnapshot.doc(registredUser.uid).get();
if(ownerSnapshots.exists){
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context)=>homecontroller(
controllUserType:ownerSnapshots.data()['Account type'].toString(),
userid: ownerSnapshots.data()['userId'].toString(),
)));
}else if(userSnapshots.exists){
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context)=>homecontroller(
controllUserType:userSnapshots.data()['Account type'].toString(),
userid: userSnapshots.data()['userId'].toString(),
)));
} else{
return null;
}
}
on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}
}
Here is My HomeController Page.
class homecontroller extends StatelessWidget {
final String controllUserType;
final String userid;
const homecontroller({Key key,#required this.controllUserType,#required this.userid}):super(key: key);
#override
Widget build(BuildContext context) {
Authservice auth
final Authservice auth=Provider.of(context).auth;
return StreamBuilder(
stream:auth.authStateChanges,
builder: (context,AsyncSnapshot<String>snapshot){
if(snapshot.connectionState==ConnectionState.active){
final bool SignedIn=snapshot.hasData;
return SignedIn?HomePage(UserType:controllUserType,userID: userid,):firstview();
}else{
return CircularProgressIndicator();
}
},
);
}
}
finally Here is My home page()
class HomePage extends StatefulWidget {
final String UserType;
final String userID;
const HomePage({Key key,#required this.UserType,#required this.userID}):super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
DateTime backButtunPressedtime;
bool isSignedIn= false;
int _CurrentIndex=0;
String owneruerID;
dynamic uploadusertypes;
List<Widget>_children;
void initState(){
super.initState();
uploadusertypes= widget.UserType;
owneruerID = widget.userID;
_children=[
TimeLinePage(),
SearchPage(), //search(),
UploadPage(UserSID:owneruerID,uploadusertypes:uploadusertypes),
NotificationsPage(),
ProfilePage(userProfileID:widget.userID),
];
if(FirebaseAuth.instance.currentUser!=null){
setState(() {
isSignedIn= true;
});
}else{
setState(() {
isSignedIn= false;
});
}
}
#override
Widget build(BuildContext context) {
if(isSignedIn){
if(widget.UserType== 'Customer'){
return Scaffold(
body: WillPopScope(
onWillPop: onwillpops,
child: buildHomeScreen(),
),
);
}
else{
return Scaffold(
body: WillPopScope(
onWillPop: onwillpops,
child:buildSignedInScreen(),
),
}return Container(
height: 0.0,
width: 0.0,
);
}
Scaffold buildSignedInScreen(){
return Scaffold(
backgroundColor: Colors.white70,
body: _agentchildren[_agentCurrentIndex],
bottomNavigationBar: CupertinoTabBar(
currentIndex: _agentCurrentIndex,
backgroundColor: Colors.black,
onTap: agentonTabchangePage,
activeColor: Colors.green,
inactiveColor: Colors.white10,
items: [
BottomNavigationBarItem(icon:Icon(Icons.home),title: Text('home'),),
BottomNavigationBarItem(icon:Icon(Icons.search)),
BottomNavigationBarItem(icon:Icon(Icons.notifications)),
BottomNavigationBarItem(icon:Icon(Icons.person_add_alt_1_sharp)),
],
),
);
}
Scaffold buildHomeScreen(){
return Scaffold(
backgroundColor: Colors.black,
body: _children[_CurrentIndex],
bottomNavigationBar: CupertinoTabBar(
currentIndex: _CurrentIndex,
backgroundColor: Colors.black,
onTap: onTabchangePage,
activeColor: Colors.green,
inactiveColor: Colors.white,
items: [
BottomNavigationBarItem(icon:Icon(Icons.home),title: Text('home'),),
BottomNavigationBarItem(icon:Icon(Icons.search)),
BottomNavigationBarItem(icon:Icon(Icons.photo_camera,size: 40,)),
BottomNavigationBarItem(icon:Icon(Icons.notifications)),
BottomNavigationBarItem(icon:Icon(Icons.person_add_alt_1_sharp)),
],
),
);
}
void onTabchangePage(int index) {
setState(() {
_CurrentIndex= index;
});
}
Future<bool> onwillpops()async {
DateTime curentTime= DateTime.now();
//if backbutton is not pressed or toast mesge closed
bool bckbutton= backButtunPressedtime==null||curentTime.difference(backButtunPressedtime)>Duration(seconds: 3);
if(bckbutton){
backButtunPressedtime= curentTime;
Fluttertoast.showToast(
msg: "Double Click to exit app",
backgroundColor: Colors.black,
textColor: Colors.white,
);
return false;
}
return true;
}
}
Here is The problem that happened to me. In my home page I use WillPopScope to Handle The device Back button, and when I close the app by using The device Back Button The app exits or closes as Expected but when Reopen again, the first white Screen page displayed and after 3 or 4 seconds The Second Black Screen page Displayed, and Stay at That Black Screen page or app Crashes
If you are using named routes and your route names start with /, then the initial route must be "/" only. Otherwise, don't use / in route names.
Also, don't hardcode named routes, you may misspell it. Instead, save it in a constants file.
I am trying to display a pop-up dialog like (+20) based on the value coming from server. I have a variable name ageRestriction which is getting the value from server. And I want to display pop-up based on the value of this variable. (Eg: If ageRestriction has the value of "18" the pop-up will be displayed only once then later on if the value will change to "20" the pop-up will be displayed once again, so these values will be stored somewhere and the pop-up will not be displayed if the same value comes again)
I have tried to do it with shared preferences unfortunately it did not work:
// initializing shared pref
#override
void initState() async{
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences prefs = await SharedPreferences.getInstance();
widget.ageRestriction = await prefs.getString("ageRestriction");
await prefs.setString("ageRestriction", widget.ageRestriction);
}
// displaying pop-up dialog
widget.ageRestriction.toString() == widget.ageRestriction ? null :
AwesomeDialog(
popContext: false,
context: context,
dialogType: DialogType.WARNING,
animType: AnimType.TOPSLIDE,
title: "${widget.ageRestriction} Warning",
desc: "We only sell this product to persons who are ${widget.ageRestriction} years old. Age will be verified upon delivery.",
btnOkText: "Continue",
btnOkOnPress: () async{
widget.onPressed();
Navigator.of(context).pop();
},
btnCancelOnPress: () {
Navigator.of(context).pop();
},
btnCancelText: S.current.cancel,
btnOkColor: Theme.of(context).accentColor,
btnCancelColor: Color(0xFF084457).withOpacity(0.9),
).show();
ageRestrict();
}
Store widget.ageRestriction in a variable in the state of the widget and then check in didUpdateWidget whether the value changed and if it did show the popup
Simple Demo App to show age restriction :
Future<String> getAgeRestrictionFromServer() async {
// write your own logic
await Future.delayed(Duration(seconds: 2));
return "22";
}
enum RequestState { LOADING, SUCCESS, ERROR }
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>{
// request status
RequestState requestState = RequestState.LOADING;
// disable multiple clickes
bool retryButtonEnabled = true;
#override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
getData();
});
}
showAgeRestrictionDialog(String age) {
return showDialog(
context: context,
child: AlertDialog(
title: Text('Age policy changed!'),
content: Text('New Age: $age'),
),
);
}
void changeRequestState(RequestState newRequestState) {
if (mounted) {
setState(() {
requestState = newRequestState;
});
}
}
Future<void> getData() async {
changeRequestState(RequestState.LOADING);
try {
// get age from server
var newAgeRestriction = await getAgeRestrictionFromServer();
// get age stored locally
SharedPreferences sharedPreferences =
await SharedPreferences.getInstance();
var previousAgeRestriction =
sharedPreferences.getString('ageRestriction');
print('$previousAgeRestriction, $newAgeRestriction');
int.parse(newAgeRestriction);
if (mounted) {
// compare previous and new age
if (previousAgeRestriction != newAgeRestriction) {
// save new age
await sharedPreferences.setString(
'ageRestriction', newAgeRestriction);
// show dialog because age changed
showAgeRestrictionDialog(newAgeRestriction);
}
}
retryButtonEnabled = true;
changeRequestState(RequestState.SUCCESS);
} catch (e) {
print(e);
retryButtonEnabled = true;
changeRequestState(RequestState.ERROR);
}
}
#override
Widget build(BuildContext context) {
var child;
if (requestState == RequestState.LOADING) {
child = Center(
child: CircularProgressIndicator(),
);
} else if (requestState == RequestState.SUCCESS) {
child = Center(
child: Text('Got data from server!'),
);
} else {
child = Center(
child: FlatButton(
color: Colors.blue,
onPressed: retryButtonEnabled
? () {
setState(() {
retryButtonEnabled = false;
});
getData();
}
: null,
child: Text('Retry')),
);
}
return Scaffold(
appBar: AppBar(
title: Text('Demo App'),
),
body: child,
);
}
}
More info about state management here