callback function not working with the button - dart

I'm trying to add forget password to my login page
when I click on the send button an HTTP request sent to the server
what I did is that
i put my HTTP request inside Future function and I call the function in onPressed but nothing happens
anything wrong ??
my HTTP function
Future<Map<String, dynamic>> send (String username, String email) async{
final Map<String, dynamic> authData ={
'Username' :username,
'Password': email,
};
final http.Response response = await http.post('url',
body: json.encode(authData),
headers: {'Content-Type': 'application/json'},
);
final Map<String, dynamic> responseData = json.decode(response.body);
bool hasError = true;
String message = 'Data is not Valid';
if ( responseData["StatusCode"] == 200 ) {
print('forget password');
showDialog(context:context, builder: (BuildContext context){
return AlertDialog(
title: Text("Note!"),
content: Text('check your email'),
actions: <Widget>[
FlatButton(child: Text("OK"),
onPressed: (){
Navigator.of(context).pop();
},)
],);
});
} else if(responseData.containsKey("StatusCode") != '200') {
message='invalid username or email ';
print('error');
}
return {'success': !hasError, 'message': message};
}
and the call back on the function
final sendbutton = Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child:RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
onPressed: ()=> send,
padding: EdgeInsets.all(12),
color: Colors.orangeAccent,
child: Text('Send', style: TextStyle(color: Colors.white)),
),
);
anything wrong?

you should fix the way you are calling the send function
final sendbutton = Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child:RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
onPressed: ()=> send(username,email),
padding: EdgeInsets.all(12),
color: Colors.orangeAccent,
child: Text('Send', style: TextStyle(color: Colors.white)),
),
);

Related

i have a case like this, how to display data based on the number/id in the API

I have a case where I want to filter data based on the semester the user chooses, for example, when selecting semester 2 it displays the data in semester 2.
but from BackEnd when you have to filter the data you have to add parameters as shown, how do you do that?
and when I want to filter by semester, I have to add a parameter to the endpoint, is there a solution?
and this is when i call the API
static Future<Map<String, DataKuliahModel>> getDataKuliah() async {
String url = Constant.baseURL;
String token = await UtilSharedPreferences.getToken();
await Future.delayed(const Duration(seconds: 4));
Map<String, DataKuliahModel> finalResult = {};
final response = await http.get(
Uri.parse(
'$url/auth/mhs_siakad/perwalian/get_paket',
),
headers: {
'Authorization': 'Bearer $token',
},
);
final result = jsonDecode(response.body)['data'] as Map<String, dynamic>;
result.forEach((key, value) {
DataKuliahModel dataKuliah = DataKuliahModel.fromMap(value);
finalResult.addAll({
key: dataKuliah,
});
});
return finalResult;
}
when it is displayed to the user
FutureBuilder(
future: Services.getDataKuliah(),
builder: (context, snapshot) {
if (snapshot.hasData) {
DataKuliahModel selectedData =
snapshot.data!['$semester'] ?? DataKuliahModel();
return Column(
children: [
Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(
Radius.circular(8),
),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 1,
blurRadius: 9,
offset: const Offset(
1, 2), // changes position of shadow
),
],
),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
selectedData.matakuliah,
style: bold6,
textAlign: TextAlign.center,
), ...
the result is like this in every card has the same value
If you want to add smt to param, try this :
Uri.parse(
'$url/auth/mhs_siakad/perwalian/get_paket?smt=${yourSmtValue}',
),

Problem in Shared Preferenced in LoginScreen. Flutter

help and explain to me in detail please how can I modify my code. I am beginner in Flutter and now I am doing tasks, the essence of which is the use of Shared Preferenced in the Login Screen and saving the user data in FireBase. When the user first entered the data, he entered the Home screen, but when the user exits the application and tries to log in again, it should be that he does not need to enter the password and login again.
Also, I knocked out such an error
import 'package:flutter/material.dart';
import 'package:logining/home_screen/home_screen.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:shared_preferences/shared_preferences.dart';
class LoginScreen extends StatefulWidget {
#override
LoginScreenState createState() {
return new LoginScreenState();
}
}
enum LoginStatus{
notSignIn,
signIn,
}
class LoginScreenState extends State<LoginScreen> {
LoginStatus _loginStatus = LoginStatus.notSignIn;
String _email, _password;
bool _obscureText = true;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
TextEditingController email = new TextEditingController();
TextEditingController password = new TextEditingController();
SharedPreferences sharedPreferences;
Future<FirebaseUser> _signInGoogle() async{
GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
GoogleSignInAuthentication gSa =await googleSignInAccount.authentication;
FirebaseUser user = await _auth.signInWithGoogle(
idToken: gSa.idToken,
accessToken: gSa.accessToken
);
print('User Name : ${user.displayName}');
return Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreen(user: user)));
}
safePref()async{
SharedPreferences preferences = await SharedPreferences.getInstance();
setState((){
preferences.setString('email', _email);
preferences.setString('password', _password);
preferences.commit();
});
}
var value;
getPref()async{
SharedPreferences preferences = await SharedPreferences.getInstance();
setState(() {
value = preferences.getInt('password');
value = preferences.getInt('email');
_loginStatus = value == 1 ? LoginStatus.signIn :LoginStatus.notSignIn;
});
}
#override
void initState(){
super.initState();
getPref();
}
#override
Widget build(BuildContext context) {
switch(_loginStatus){
case LoginStatus.notSignIn:
return Scaffold(
appBar: AppBar(
title: Text('Login'),
),
resizeToAvoidBottomPadding: false,
body: ListView(children: <Widget>[
Container(
child: Form(
key: _formKey,
autovalidate: true,
child: Column(
children: <Widget>[
SizedBox(
height: 50,
),
Padding(
child: Image.asset(
'images/logo.png',
width: 100.0,
height: 100.0,
),
padding: EdgeInsets.fromLTRB(50, 0, 50, 40),
),
Padding(
padding: EdgeInsets.fromLTRB(25, 0, 50, 10),
child: TextFormField(
controller: email,
validator: (email) {
if (email.isEmpty) {
return 'Provide an Email';
}
},
style: TextStyle(
color: Color(0xFF01579B),
fontSize: 18.0,
),
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
),
hintText: 'Enter your Email',
labelText: "Email",
icon: Padding(
padding: EdgeInsets.only(top: 20.0),
child: Icon(Icons.email),
)),
onSaved: (email) => _email = email,
),
),
Padding(
padding: EdgeInsets.fromLTRB(25, 0, 50, 10),
child: TextFormField(
controller: password,
validator: (password) {
if (password.isEmpty) {
return 'Provide an password';
}
},
obscureText: _obscureText,
style: TextStyle(
color: Color(0xFF01579B),
fontSize: 18.0,
),
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
),
hintText: 'Enter your password',
labelText: "Password",
icon: Padding(
padding: EdgeInsets.only(top: 15.0),
child: Icon(Icons.lock),
),
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_obscureText = !_obscureText;
});
},
child: Icon(
_obscureText
? Icons.visibility
: Icons.visibility_off,
semanticLabel: _obscureText
? 'show password'
: 'hide password',
),
),
),
onSaved: (password) => _password = password,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: RaisedButton(
color: Color(0xFFD50000),
textColor: Color(0xFFFFFFFF),
child: Text('Login with Google'),
onPressed:(){ _signInGoogle().then((FirebaseUser user){
print(user);
}).catchError((onError){
print(onError);
});
}
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: RaisedButton(
color: Color(0xFF448AFF),
textColor: Color(0xFFFFFFFF),
child: Text('Login'),
onPressed: signIn,
),
),
]),
Padding(
padding:
EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: FlatButton(
textColor: Color(0xFF448AFF),
child: Text('Forgot Password'),
onPressed: () {
print('onPressed');
},
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(50, 70, 0, 10),
child: Text(
'Still do not have an account ',
style: TextStyle(color: Color(0xFF9E9E9E)),
),
),
Padding(
padding: EdgeInsets.fromLTRB(0, 70, 30, 10),
child: FlatButton(
textColor: Color(0xFF448AFF),
child: Text('registration'),
onPressed: () {
Navigator.of(context).pushNamedAndRemoveUntil(
'/registration', (Route<dynamic> route) => false);
},
),
),
],
),
],
),
),
),
]),
);
break;
case LoginStatus.signIn:
return HomeScreen();
break;
}
}
Future<void> signIn() async {
final formState = _formKey.currentState;
if(formState.validate()) {
setState(() {
_loginStatus = LoginStatus.signIn;
formState.save();
});
try {
FirebaseUser user = await FirebaseAuth.instance.signInWithEmailAndPassword(email: _email, password: _password);
}catch(e){
print(e.message);
}
}
}
}
after looking at your code i think i see where the problem is. The way i have understood your code is that the method 'safePref' is called to save password and email to shared preferences. Also, i hope its true that the method to get from shared preferences is 'getPref'. The error comes in that the value stored is a String
preferences.setString('email', _email);
preferences.setString('password', _password);
and the value read from storage is expected to be an Integer
value = preferences.getInt('password');
value = preferences.getInt('email');
You should change the last two to be
value = preferences.getString('password');
value = preferences.getString('email');
since the value stored is a String. To compare the Strings against integers you can change the statement
_loginStatus = value == 1 ? LoginStatus.signIn :LoginStatus.notSignIn;
to be
_loginStatus = int.parse(value) == 1 ? LoginStatus.signIn :LoginStatus.notSignIn;
My solution should solve the String problem but i think it will always return a false unless the Users Password is '1'.
Hope this helps. Thanks.
You have as String value and try to read as int value here's the problem . You should first read as String your email and password and then parse them to int.
var value;
getPref()async{
SharedPreferences preferences = await SharedPreferences.getInstance();
setState(() {
value = preferences.getString('password');
value = preferences.getString('email');
_loginStatus = int.parse(value) == 1 ? LoginStatus.signIn :LoginStatus.notSignIn;
});
}

What is the problem? Shared Preferences in LoginScreen does not work every time

I'm trying to do Shared Preferences. It should work so that when the user first logged in and entered his password and his login was transferred to Nome Skreen, the next time he logs into the application he will not need to enter his data and Nome Skreen will immediately open. But at the moment, Shared Preferenses works through time.
I can not get rid of this problem
My code
import 'package:flutter/material.dart';
import 'package:logining/home_screen/home_screen.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:shared_preferences/shared_preferences.dart';
class LoginScreen extends StatefulWidget {
#override
LoginScreenState createState() {
return new LoginScreenState();
}
}
enum LoginStatus{
notSignIn,
signIn,
}
class LoginScreenState extends State<LoginScreen> {
LoginStatus _loginStatus = LoginStatus.notSignIn;
var _email, _password;
bool _obscureText = true;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
TextEditingController email = new TextEditingController();
TextEditingController password = new TextEditingController();
SharedPreferences sharedPreferences;
savePref()async{
SharedPreferences preferences = await SharedPreferences.getInstance();
setState((){
preferences.setString('email', _email);
preferences.setString('password', _password);
preferences.commit();
});
}
var value;
getPref()async{
SharedPreferences preferences = await SharedPreferences.getInstance();
setState(() {
value = preferences.getString("email");
value = preferences.getString("password");
_loginStatus = value == null ? LoginStatus.notSignIn : LoginStatus.signIn;
});
}
#override
void initState(){
super.initState();
getPref();
}
#override
Widget build(BuildContext context) {
switch(_loginStatus){
case LoginStatus.notSignIn:
return Scaffold(
appBar: AppBar(
title: Text('Login'),
),
resizeToAvoidBottomPadding: false,
body: ListView(children: <Widget>[
Container(
child: Form(
key: _formKey,
autovalidate: true,
child: Column(
children: <Widget>[
SizedBox(
height: 50,
),
Padding(
child: Image.asset(
'images/logo.png',
width: 100.0,
height: 100.0,
),
padding: EdgeInsets.fromLTRB(50, 0, 50, 40),
),
Padding(
padding: EdgeInsets.fromLTRB(25, 0, 50, 10),
child: TextFormField(
controller: email,
validator: (email) {
if (email.isEmpty) {
return 'Provide an Email';
}
},
style: TextStyle(
color: Color(0xFF01579B),
fontSize: 18.0,
),
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
),
hintText: 'Enter your Email',
labelText: "Email",
icon: Padding(
padding: EdgeInsets.only(top: 20.0),
child: Icon(Icons.email),
)),
onSaved: (email) => _email = email,
),
),
Padding(
padding: EdgeInsets.fromLTRB(25, 0, 50, 10),
child: TextFormField(
controller: password,
validator: (password) {
if (password.isEmpty) {
return 'Provide an password';
}
},
obscureText: _obscureText,
style: TextStyle(
color: Color(0xFF01579B),
fontSize: 18.0,
),
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
),
hintText: 'Enter your password',
labelText: "Password",
icon: Padding(
padding: EdgeInsets.only(top: 15.0),
child: Icon(Icons.lock),
),
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_obscureText = !_obscureText;
});
},
child: Icon(
_obscureText
? Icons.visibility
: Icons.visibility_off,
semanticLabel: _obscureText
? 'show password'
: 'hide password',
),
),
),
onSaved: (password) => _password = password,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: RaisedButton(
color: Color(0xFFD50000),
textColor: Color(0xFFFFFFFF),
child: Text('Login with Google'),
onPressed:(){ _signInGoogle().then((FirebaseUser user){
print(user);
}).catchError((onError){
print(onError);
});
}
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: RaisedButton(
color: Color(0xFF448AFF),
textColor: Color(0xFFFFFFFF),
child: Text('Login'),
onPressed: signIn,
),
),
]),
Padding(
padding:
EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: FlatButton(
textColor: Color(0xFF448AFF),
child: Text('Forgot Password'),
onPressed: () {
print('onPressed');
},
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(50, 70, 0, 10),
child: Text(
'Still do not have an account ',
style: TextStyle(color: Color(0xFF9E9E9E)),
),
),
Padding(
padding: EdgeInsets.fromLTRB(0, 70, 30, 10),
child: FlatButton(
textColor: Color(0xFF448AFF),
child: Text('registration'),
onPressed: () {
Navigator.of(context).pushNamedAndRemoveUntil(
'/registration', (Route<dynamic> route) => false);
},
),
),
],
),
],
),
),
),
]),
);
break;
case LoginStatus.signIn:
return HomeScreen();
break;
}
}
signIn() async {
final formState = _formKey.currentState;
if(formState.validate()) {
formState.save();
try {
FirebaseAuth.instance.signInWithEmailAndPassword(email: _email, password: _password);
_loginStatus = LoginStatus.signIn;
// savePref();
Navigator.of(context).pushNamedAndRemoveUntil(
'/list', (Route<dynamic> route) => false);
}catch(e){
print(e.message);
}
}
}
Future<FirebaseUser> _signInGoogle() async{
GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
GoogleSignInAuthentication gSa =await googleSignInAccount.authentication;
FirebaseUser user = await _auth.signInWithGoogle(
idToken: gSa.idToken,
accessToken: gSa.accessToken
);
print('User Name : ${user.displayName}');
return Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreen(user: user)));
}
}
You should use a FutureBuilder instead of a normal Build method inside your LoginScreenState because a normal build method will be called before your data is fetched from the Shared Preferences using the async method,unlike the FutureBuilder which will wait for the result to be fetched and set the state of your Stateful widget accordingly. So your code should be like this :
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getPref(),
builder: (BuildContext context, AsyncSnapshot<SharedPreferences> snapshot) {
if(snapshot.connectionState == ConnectionState.done){
_loginStatus = snapshot.data.getKeys.length > 0 ? LoginStatus.signIn : LoginStatus.notSignIn ;
}else{
return Container() ;
}
}
);
}
this way you'll always get the right login status, after that you can use it for whatever you want to.

Async call value is NULL for the first time, causing assertion error while building MainPage (Widget dirty)

I am working on a flutter widget which needs to load and update data in a Text with rest call. async call fetchPatientCount brings the data from REST resource and update the counter inside the setState method.
As a result of the below implementation, since the build method called twice, the counter value is NULL for the first time and causing the below exception.However for the second time the value is being populated.
flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
flutter: The following assertion was thrown building MainPage(dirty, state: _MainPageState#9e9d8):
flutter: 'package:flutter/src/widgets/text.dart': Failed assertion: line 235 pos 15: 'data != null': is not
flutter: true.
Any help will be appreciated related to the issue.
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
String counter;
#override
void initState() {
super.initState();
fetchPatientCount().then((val) {
setState(() {
counter = val.count.toString();
});
});
}
#override
Widget build(BuildContext context) {
String text;
if(counter!=null) {
text = counter;
}
return Scaffold(
appBar: AppBar(
elevation: 2.0,
backgroundColor: Colors.white,
title: Text('Dashboard',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w700,
fontSize: 30.0)),
),
body: StaggeredGridView.count(
crossAxisCount: 2,
crossAxisSpacing: 12.0,
mainAxisSpacing: 12.0,
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
children: <Widget>[
_buildTile(
Padding(
padding: const EdgeInsets.all(24.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Total Views',
style: TextStyle(color: Colors.blueAccent)),
Text(text,/* Here text is NULL for the first time */
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w700,
fontSize: 34.0))
],
),
Material(
color: Colors.blue,
borderRadius: BorderRadius.circular(24.0),
child: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Icon(Icons.timeline,
color: Colors.white, size: 30.0),
)))
]),
),
),
],
staggeredTiles: [StaggeredTile.extent(2, 110.0)],
));
}
Widget _buildTile(Widget child, {Function() onTap}) {
return Material(
elevation: 14.0,
borderRadius: BorderRadius.circular(12.0),
shadowColor: Color(0x802196F3),
child: InkWell(
// Do onTap() if it isn't null, otherwise do print()
onTap: onTap != null
? () => onTap()
: () {
print('Not set yet');
},
child: child));
}
}
class PatientCount {
int count;
double amount;
PatientCount({this.count, this.amount});
PatientCount.fromJson(Map<String, dynamic> map)
: count = map['count'],
amount = map['amount'];
}
Future<PatientCount> fetchPatientCount() async {
var url = "http://localhost:9092/hms/patients-count-on-day";
Map<String, String> requestHeaders = new Map<String, String>();
requestHeaders["Accept"] = "application/json";
requestHeaders["Content-type"] = "application/json";
String requestBody = '{"consultedOn":' + '16112018' + '}';
http.Response response =
await http.post(url, headers: requestHeaders, body: requestBody);
final statusCode = response.statusCode;
final Map responseBody = json.decode(response.body);
if (statusCode != 200 || responseBody == null) {
throw new Exception(
"Error occured : [Status Code : $statusCode]");
}
return PatientCount.fromJson(responseBody['responseData']['PatientCountDTO']);
}
I solved my self, used FutureBuilder to resolve the issue.
Here is the full code below.
class PatientCount {
int count;
double amount;
PatientCount({this.count, this.amount});
PatientCount.fromJson(Map<String, dynamic> map)
: count = map['count'],
amount = map['amount'];
}
Future<PatientCount> fetchPatientCount() async {
var url = "http://localhost:9092/hms/patients-count-on-day";
Map<String, String> requestHeaders = new Map<String, String>();
requestHeaders["Accept"] = "application/json";
requestHeaders["Content-type"] = "application/json";
String requestBody = '{"consultedOn":' + '16112018' + '}';
http.Response response =
await http.post(url, headers: requestHeaders, body: requestBody);
final statusCode = response.statusCode;
final Map responseBody = json.decode(response.body);
if (statusCode != 200 || responseBody == null) {
throw new FetchPatientCountException(
"Error occured : [Status Code : $statusCode]");
}
return PatientCount.fromJson(responseBody['responseData']['PatientCountDTO']);
}
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 2.0,
backgroundColor: Colors.white,
title: Text('Dashboard',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w700,
fontSize: 30.0)),
),
body: StaggeredGridView.count(
crossAxisCount: 2,
crossAxisSpacing: 12.0,
mainAxisSpacing: 12.0,
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
children: <Widget>[
_buildTile(
Padding(
padding: const EdgeInsets.all(24.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Total Views',
style: TextStyle(color: Colors.blueAccent)),
/*Text(get,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w700,
fontSize: 34.0))*/
buildCountWidget()
],
),
Material(
color: Colors.blue,
borderRadius: BorderRadius.circular(24.0),
child: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Icon(Icons.timeline,
color: Colors.white, size: 30.0),
)))
]),
),
),
],
staggeredTiles: [StaggeredTile.extent(2, 110.0)],
));
}
Widget _buildTile(Widget child, {Function() onTap}) {
return Material(
elevation: 14.0,
borderRadius: BorderRadius.circular(12.0),
shadowColor: Color(0x802196F3),
child: InkWell(
// Do onTap() if it isn't null, otherwise do print()
onTap: onTap != null
? () => onTap()
: () {
print('Not set yet');
},
child: child));
}
Widget buildCountWidget() {
Widget vistitCount = new Center(
child: new FutureBuilder<PatientCount>(
future: fetchPatientCount(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return new Text(snapshot.data.count.toString(),
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w700,
fontSize: 34.0));
} else if (snapshot.hasError) {
return new Text("${snapshot.error}");
}
// By default, show a loading spinner
return new CircularProgressIndicator();
},
),
);
return vistitCount;
}
}
If it's null, build a widget that says that it's loading. It will build the actual widgets in the second call that you mentioned.
Basically, do this:
#override
Widget build(BuildContext context) {
String text;
if(counter!=null) {
text = counter;
} else {
return Text("loading..."); // or a fancier progress thing
}
fetchPatientCount().then((val) {
setState(() {
counter = val.count.toString();
});
});
That's expected behavior. "async" means the result will be available eventually later and then the code passed to then will be executed.
Flutter doesn't wait for that. It calls build() for every frame.
Perhaps you wanted to change
if(counter!=null) {
text = counter;
}
to
if(counter!=null) {
text = counter;
} else {
text = 'waiting ...';
}
because otherwise text will be null and Text(null) causes the error you got.

Login form in flutter

I´m create a simple login in flutter. This login connect to a API. For do this I retrieve inputs value and send to a method, but return
type '_InternalLinkedHashMap' is not a subtype of type 'Map'
This is my model
class Login {
final String usuario, password;
Login({this.usuario, this.password});
factory Login.fromJson(Map<String, dynamic> json) {
return Login(
usuario: json['usuario'] as String,
password: json['password'] as String,
);
}
}
And this is my main class
import 'package:flutter/material.dart';
import 'package:igota/screens/home/home_page.dart';
import 'package:igota/model/login.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
class LoginPage extends StatefulWidget {
static String tag = 'login-page';
#override
_LoginPageState createState() => new _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final _formKey = GlobalKey<FormState>();
final userValue = new TextEditingController();
final passwordValue = new TextEditingController();
#override
Widget build(BuildContext context) {
final logo = Hero(
tag: 'hero',
child: CircleAvatar(
backgroundColor: Colors.transparent,
radius: 48.0,
child: Image.asset('assets/logo.png'),
),
);
final username = TextFormField(
controller: userValue,
validator: (value) {
if (value.isEmpty) {
return 'Introduce un nombre';
}
},
keyboardType: TextInputType.emailAddress,
autofocus: false,
decoration: InputDecoration(
hintText: 'Usuario',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
),
);
final password = TextFormField(
controller: passwordValue,
validator: (value) {
if (value.isEmpty) {
return 'Introduce una contraseña';
}
},
autofocus: false,
obscureText: true,
decoration: InputDecoration(
hintText: 'Contraseña',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
),
);
Widget _buildLoginButton(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Material(
borderRadius: BorderRadius.circular(30.0),
child: MaterialButton(
minWidth: 200.0,
height: 42.0,
onPressed: () {
fetchPost(userValue, passwordValue);
//final snackBar = SnackBar(
// content: Text(
// 'Usuario/Contraseña incorrecto',
// textAlign: TextAlign.center,
//));
//Scaffold.of(context).showSnackBar(snackBar);
if (_formKey.currentState.validate()) {
Navigator.of(context).pushNamed(HomePage.tag);
}
},
color: Colors.blue[300],
child: Text('Entrar', style: TextStyle(color: Colors.white)),
),
),
);
}
final forgotLabel = FlatButton(
child: Text(
'¿Contraseña olvidada?',
style: TextStyle(color: Colors.black54),
),
onPressed: () {},
);
return Scaffold(
backgroundColor: Colors.white,
body: Builder(
builder: (context) => Center(
child: Form(
key: _formKey,
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.only(left: 24.0, right: 24.0),
children: <Widget>[
logo,
SizedBox(height: 48.0),
username,
SizedBox(height: 8.0),
password,
SizedBox(height: 24.0),
_buildLoginButton(context),
forgotLabel
],
),
)),
),
);
}
}
//Test
Future<Login> fetchPost(user, pass) async {
Map headers = {
'Content-type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
'URL',
body: {"usuario": user.text, "password": pass.text},
headers: headers);
final responseJson = json.decode(response.body);
return Login.fromJson(responseJson);
}
So i need to return response and check if correct or incorrect to show snackbar. I don't know exactly what i'm doing right or wrong :$
You need to define the type of headers like this:
Map<String, String> headers = {
'Content-type': 'application/json',
'Accept': 'application/json',
};
EDIT: You need to use json.encode on the body of a request with 'Content-type': 'application/json' as well.
EDIT2:
Future<Login> fetchPost(user, pass) async {
Map<String, String> headers = {
'Content-type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
'URL',
body: json.encode({"usuario": user.text, "password": pass.text}),
headers: headers);
final responseJson = json.decode(response.body);
return Login.fromJson(responseJson);
}

Resources