I want to refresh my List when hitting the back button on the details page (which the List page links from). However, the method I need to run is a Future and it seems that causes some issues.
I have used this approach: https://stackoverflow.com/questions/49933272/how-to-refresh-a-page-after-back-bottun-pressed?rq=1#=
Here is a shot of the error:
And here is the method:
// Load list items
Future _loadItems() async {
// setState(() => _isLoading = true);
List<CNotification> _listItems = new List<CNotification>();
SharedPreferences prefs = await SharedPreferences.getInstance();
String _usr = prefs.getString('usr');
String _pwd = prefs.getString('pwd');
String _communityId = prefs.getInt('communityid').toString();
final response = await http.get(helperConnectionString +
'GetNotifications?usr=$_usr&pwd=$_pwd&communityid=$_communityId');
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON
List data = json.decode(response.body);
for (var i = 0; i < data.length; i++) {
String _title = "";
data[i]['MessageText'].toString().length > 25
? _title =
data[i]['MessageText'].toString().substring(0, 25) + '...'
: _title = data[i]['MessageText'].toString();
DateTime entryCreated =
DateTime.parse(data[i]['DateCreated'].toString());
String _dRead =
DateFormat.yMd().add_jms().format(entryCreated).toString();
_listItems.add(new CNotification(int.parse(data[i]['Id'].toString()),
_title, _dRead, data[i]['DateRead'] == null ? false : true));
}
setState(() {
_items = _listItems;
_isLoading = false;
});
} else {
setState(() {
_isLoading = false;
});
print('Error');
}
}
Anyone?
/Bob
Here is what you are looking for.
Navigator.of(context).push(MaterialPageRoute(builder: (context) => SomePage())).then((_) => _loadItems())
But I would recommend you to use async/await everywhere:
#override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: _showSomePage,
child: Text('Show some page'),
);
}
void _showSomePage() async {
await Navigator.of(context).push(MaterialPageRoute(
builder: (context) => SomePage(),
));
await _loadItems();
}
Future<void> _loadItems() async {
// ...
}
Inline version:
#override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: () async {
await Navigator.of(context).push(MaterialPageRoute(
builder: (context) => SomePage(),
));
await _loadItems();
},
child: Text('Show some page'),
);
}
Related
My filter function that is showFilterDialog() only returns the first element/card in my index instead of the one with the correct value. I even used my sorting function to change the arrangement of my elements but still it returned the new first index after sorting instead of the correct value. Any ideas to why is that happening? (the values i'm trying to filter are correct and do exist in my firebase DB)
void showFilterDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
title: const Text('Filter by: '),
children: <Widget>[
SimpleDialogOption(
onPressed: () {
setState(() {
filteredOfferList = traineeApplications.offerList;
});
Navigator.pop(context);
},
child: const Text('All'),
),
SimpleDialogOption(
onPressed: () {
setState(() {
filteredOfferList = traineeApplications.offerList
.where((offer) => offer['currentInstitution'] == 'qatar university')
.toList();
});
Navigator.pop(context);
},
child: const Text('Qatar University'),
),
SimpleDialogOption(
onPressed: () {
setState(() {
filteredOfferList = traineeApplications.offerList
.where((offer) => offer['currentInstitution'] == 'texas')
.toList();
});
Navigator.pop(context);
},
child: const Text('Texas'),
),
],
);
},
);
}
The following is how I initiate my fillteredOffer List.
class _MyStatefulWidgetState extends State<traineeApplications> {
TraineesController tc = Get.find<TraineesController>();
String query = ""; // variable to hold the search query
String searchText = "";
List filteredOfferList = []; // variable to hold the filtered list of offers
#override
void initState() {
super.initState();
fetchDatabaseList();
filteredOfferList = traineeApplications.offerList;
}
fetchDatabaseList() async {
dynamic resultant = await getUsersList();
if (resultant == null) {
print('Unable to retrieve');
} else {
setState(() {
traineeApplications.offerList = resultant;
filteredOfferList = traineeApplications.offerList;
});
}
}
CollectionReference _collectionRef =
FirebaseFirestore.instance.collection('Trainees');
Future getUsersList() async {
List itemsList = [];
try {
await _collectionRef.get().then((querySnapshot) {
querySnapshot.docs.forEach((element) {
print(element);
itemsList.add(element);
});
});
return itemsList;
} catch (e) {
print(e.toString());
return null;
}
}
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 using shared preference to pass data from one screen to other, it was working perfectly few days ago, but now it is sending this error
Invalid argument(s) (value): Must not be null
i'm calling login api, it is running sucessfully, i am getting api data on its response but it goes to catch part after print the data, it is not navigating to other screen, here is the login function code
SharedPreferences myPrefs;
Future login() async {
Dio dio = new Dio();
try {
data = {
'username':"Munib khatri",
'password':"Munib123",
'date': formattedDate
};
await dio
.post(localhostUrlLogin, data: json.encode(data),)
.then((onResponse) async {
print(onResponse.data);
String name = (onResponse.data['User']['username']);
String email = (onResponse.data['User']['email']);
String designation = (onResponse.data['User']['Designation']);
String token = (onResponse.data['AccessToken']);
//here i am calling another api
data={
"token":token,
"username":name,
"leave":"Approved",
"type":"maternity"
};
dio
.post(localHostUrlleaveCount, data: json.encode(data))
.then((onResponse) async {
int sickCount=(onResponse.data['sick']);
int annualCount=(onResponse.data['annual']);
await myPrefs.setInt('sickCount', sickCount);
await myPrefs.setInt('annualCount', annualCount);
}).catchError((onerror){
});
await myPrefs.setString('name', name);
await myPrefs.setString('email', email);
await myPrefs.setString('designation', designation);
Navigator.push(
context, new MaterialPageRoute(builder: (context) => Navigation()));
});
} catch (e) {
print(e.toString());
}
}
Navigation:
class Navigation extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
theme: new ThemeData(primaryColor: Colors.blue),
home: EmployeeNavigation(),
);
}
}
int _selectedTab = 0;
final _pageOptions = [Home(), location(), Profile()];
String getname = "";
String getemail = "";
String getdesignation = "";
String getaccesstoken = "";
// ignore: must_be_immutable
class EmployeeNavigation extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return EmployeeNavigationState();
}
}
class EmployeeNavigationState extends State<EmployeeNavigation> {
var email;
var designation;
var date;
bool valuefirst = false;
String backtext = "";
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
if (_selectedTab == 0) {
return true;
}
setState(() {
_selectedTab = 0;
});
return false;
},
child: Scaffold(
drawer: NavigationDrawerWidget(), //this is a drawer file
body: _pageOptions[_selectedTab],
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.blue[50],
type: BottomNavigationBarType.fixed,
currentIndex: _selectedTab,
onTap: (value) {
print(value);
setState(() {
_selectedTab = value;
});
},
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: "Home"),
BottomNavigationBarItem(
icon: Icon(Icons.location_on), label: "Location"),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: "Profile",
),
],
)));
}
}
i am getting response of both api, but can't navigate to other screen.
myPrefs doesn't seem to be initialized !!!
Try:
Future login() async {
Dio dio = new Dio();
var myPrefs = await SharedPreferences.getInstance();
...
}
i just need when the user open the screen the notification icon button change when he click, it's value is coming from shared preferences. the problem is the icon is never changed!
the initState code:
#override
void initState() {
super.initState();
_isActiveNotification = _notificationGetState();
}
_notificationGetState function is:
//getting notification on/off
Future<bool> _notificationGetState() async {
final SharedPreferences _prefs = await SharedPreferences.getInstance();
return _prefs.getBool('notification') ?? true;
}
_isActiveNotification variable is:
late Future<bool> _isActiveNotification;
the class of the notification icon button is:
class _NoificationActivationButton extends StatefulWidget {
_NoificationActivationButton();
#override
_NoificationActivationButtonState createState() =>
_NoificationActivationButtonState();
}
class _NoificationActivationButtonState
extends State<_NoificationActivationButton> {
#override
Widget build(BuildContext context) {
return FutureBuilder<bool>(
//function haveing the return value
future: _isActiveNotification,
builder: (context, snapshot) {
bool data = snapshot.data!;
return IconButton(
icon: Icon(
data
? Icons.notifications_active_outlined
: Icons.notifications_off_outlined,
color: Colors.white,
size: 40,
),
onPressed: () {
setState(() {
data = !data;
});
},
);
});
}
just call setstate
onPressed: () {
data = !data;
// just call setstate((){});
},
Make data a global state.
NOTE: I'm only assuming that you will only call _notificationGetState once (in initState).
Sample...
class _NoificationActivationButtonState
extends State<_NoificationActivationButton> {
final bool _isOtherVersion = true;
late Future<bool> _isActiveNotification;
bool? _data;
#override
void initState() {
super.initState();
_isActiveNotification = _notificationGetState();
}
//getting notification on/off
Future<bool> _notificationGetState() async {
final SharedPreferences _prefs = await SharedPreferences.getInstance();
return _isOtherVersion
? _prefs.getBool('notification') ?? true
: _data = _prefs.getBool('notification') ?? true;
}
#override
Widget build(BuildContext context) {
return FutureBuilder<bool>(
//function haveing the return value
future: _isActiveNotification,
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return const CircularProgressIndicator();
}
if (_isOtherVersion && _data == null) {
_data = snapshot.data;
}
return IconButton(
icon: Icon(
_data!
? Icons.notifications_active_outlined
: Icons.notifications_off_outlined,
color: Colors.white,
size: 40,
),
onPressed: () => setState(() => _data = !_data!),
);
},
);
}
}
So I have a listview with which I used Future to fetch data and it displays fine. Now am trying to parse the value on the clicked item from the listview page to another page that will show details of the item click. Please how do I achieve this?
The Future
List dealData = List();
Future<String> _fetchComment() async {
setState(() {
isLoading = true;
debugPrint("emirate state");
});
try {
debugPrint("emirate try");
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
print('connected');
debugPrint("emirate connect");
String url;
debugPrint("my select:$_mySelection");
if (_mySelection == null && _myFeatureSelection == null) {
url = "my rest api";
} else if (_myFeatureSelection != null) {
url =
"my rest api";
_mySelection = null;
} else if (_mySelection != null && _myFeatureSelection == null) {
url = "my rest api";
}
print("our url:$url");
var res = await http
.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
var resBody = json.decode(res.body);
debugPrint("emirate url:$url");
setState(() {
dealData = resBody;
isLoading = false;
});
print(resBody);
debugPrint("emirate:$resBody");
return "Sucess";
} else {
throw Exception('Failed to load profile');
}
} on SocketException catch (_) {
print('not connected');
setState(() => isLoading = false);
Navigator.popUntil(
context, (_) => !Navigator.canPop(context));
Navigator.pushReplacement(
context,
new MaterialPageRoute(
builder: (BuildContext context) => NoInternet()));
}
}
My listview and onclick
dealData
.map(
(position) => FutureBuilder<String>(
future: getDistance(
position["lat"],
position["lng"])
.then((value) =>
value.toString()),
builder: (context, snapshot) {
double myrate = double.parse(
position["ratings"] ==
null
? "0"
: position["ratings"]);
return Container(
child:Card(child:
GestureDetector(
onTap: () {
print(position); // position printed here
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext ctx) => Maps(position)));
},
).toList(),
My Map Class
class mapsFinal extends StatefulWidget {
final int position;
const mapsFinal(this.position);
#override
_MapsState createState() => _MapsState ();
}
class _MapsState extends State<mapsFinal> {
Widget build(BuildContext context) {
return Text("title" + widget.position.toString());
}
}
Please I need a second page that will display the item I clicked on here.
This is the simplest example of passing a value to a widget called "Maps":
// BOILERPLATE CODE TO MAKE THE EXAMPLE RUN
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Maps("THE VALUE"),
),
),
);
}
}
// THIS IS THE CLASS YOU NEED TO LOOK AT:
class Maps extends StatefulWidget {
final String position;
const Maps(this.position);
#override
_MapsState createState() => _MapsState ();
}
class _MapsState extends State<Maps> {
Widget build(BuildContext context) {
return Text("You passed: " + widget.position);
}
}