Flutter shared preferences issue with setInt - flutter

im trying to build an app which consists of 3 roles, student teacher and parent. I thought of implementing the authentication using auth change stream and shared preferences. ie setInt('usertype',1) for student, 2 for teacher and 3 for parent.
this is my student registration screen where if the user is successfully registered, im setting the usertype as 1, also i did the same for teacher and parent registration screen.
class StudentRegisterScreen extends StatefulWidget {
final Function toggleView;
StudentRegisterScreen({this.toggleView});
#override
_StudentRegisterScreenState createState() => _StudentRegisterScreenState();
}
class _StudentRegisterScreenState extends State<StudentRegisterScreen> {
final AuthService _authService = AuthService();
final _formkey = GlobalKey<FormState>();
final usertype = await SharedPreferences.getInstance();
//String name = '';
//String email = '';
//String password = '';
#override
Widget build(BuildContext context) {
//String _message = '';
Size size = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: HexColor(studentPrimaryColour),
body: SafeArea(
child: SingleChildScrollView(
child: Form(
key: _formkey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 20.0,
),
HeadingText(
text: 'Register',
size: 60.0,
color: Colors.white,
),
Container(
height: 20.0,
child: HeadingText(
text: AuthService().message,
size: 20.0,
color: Colors.white,
),
),
SizedBox(
height: 25.0,
),
RoundedInputField(
hintText: 'Name',
validator: (val) =>
val.isEmpty ? 'Oops! you left this field empty' : null,
onChanged: (val) {
name = val;
},
),
SizedBox(
height: 5.0,
),
RoundedInputField(
hintText: 'Email',
validator: (val) => val.isEmpty ? 'enter an email' : null,
onChanged: (val) {
email = val;
},
),
SizedBox(
height: 5.0,
),
RoundedInputField(
hintText: 'Password',
validator: (val) =>
val.isEmpty ? 'atleast provide a password' : null,
boolean: true,
onChanged: (val) {
password = val;
}),
SizedBox(
height: 5.0,
),
Container(
margin: EdgeInsets.symmetric(vertical: 10),
width: size.width * 0.8,
child: ClipRRect(
borderRadius: BorderRadius.circular(29),
child: FlatButton(
padding:
EdgeInsets.symmetric(vertical: 20, horizontal: 40),
color: Colors.white,
onPressed: () async {
//
// if (_formkey.currentState.validate()) {
// print(email);
// print(password);
usertype.setInt('usertype',1);
// dynamic result =
// await _authService.registerWithEmailpasswd(
// email,
// password,
// name,
// );
//
},
child: HeadingText(
color: HexColor(studentPrimaryColour),
text: 'Register',
size: 12.0,
),
),
),
),
SizedBox(
height: 15.0,
),
InkWell(
onTap: () {
// Navigator.pop(context);
widget.toggleView();
},
child: HeadingText(
text: 'Already registered?',
color: Colors.white,
size: 10,
),
),
],
),
),
),
),
);
}
}
but im getting an error
I/flutter (13157): 0
E/flutter (13157): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method 'setInt' was called on null.
E/flutter (13157): Receiver: null
E/flutter (13157): Tried calling: setInt("usertype", 1)
this below is my wrapper class right now, I thought of printing the values on to the console before proceeding further, i will be implementing switch cases for showing the different user screens
class Welcomescreen extends StatefulWidget {
#override
_WelcomescreenState createState() => _WelcomescreenState();
}
class _WelcomescreenState extends State<Welcomescreen> {
SharedPreferences userDetails;
int usertype;
#override
void initState() {
// TODO: implement initState
super.initState();
checkUserType();
}
void checkUserType() async {
userDetails = await SharedPreferences.getInstance();
setState(() {
usertype = userDetails.getInt('usertype') ?? 0;
});
print(usertype);
}
#override
Widget build(BuildContext context) {
//final user = Provider.of<UserModel>(context);
return Body();
}
}

userType is referencing a future value SharedPreference.getInstance(), by creating final userType = await SharedPrefence.getInstance() you're telling the code that calling userType will return a Future of SharedPrefence.getInstance(), is not resolving to the SharedPreference class until you actually await for it (using await is not doing anything because you're not really inside an asyn function)
try calling it like this:
onPressed: () async {
(await usertype).setInt('usertype',1);
// or maybe (userType).setInt('usertype',1);
}
userType will be replaced for the value you're referencing (await SharedPreference.getInstance())
for the program it looks like this:
onPressed: () async {
(await SharedPreference.getInstance()).setInt('usertype',1);
}
first it needs to await the furure, after that you can actually call its methods

Related

Error: NoSuchMethodError: 'then' Dynamic call of null. Receiver: null

Does anyone know the cause of this error? I have tried many ways but still don't know where the problem is.
Database.dart
import 'package:fitness_app/Login/login_data.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
class DatabaseService {
static final DatabaseService _databaseService = DatabaseService._internal();
factory DatabaseService() => _databaseService;
DatabaseService._internal();
static Database? _database;
Future<Database> get database async {
if (_database != null) return _database!;
_database = await _initDatabase();
return _database!;
}
Future<Database> _initDatabase() async {
final databasePath = await getDatabasesPath();
final path = join(databasePath, 'conference.database');
return await openDatabase(
path,
onCreate: _onCreate,
version: 1,
onConfigure: (db) async => await db.execute('PRAGMA foreign_keys = ON'),
);
}
Future<void> _onCreate(Database db, int version) async {
await db.execute(
'CREATE TABLE login(id INTEGER PRIMARY KEY, name TEXT, username TEXT, password TEXT)',
);
}
verifyuser(String user, String pass) {}
insertLoginData(Logindata logindata) {}
}
Login.dart
import 'package:fitness_app/Login/signup.dart';
import 'package:flutter/material.dart';
import 'login_data.dart';
import 'package:fitness_app/Database/database.dart';
import 'package:fitness_app/home_page.dart';
class Login extends StatefulWidget {
const Login({Key? key, this.login}) : super(key: key);
final Logindata? login;
#override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
String email = "a";
String pass = "a";
TextEditingController emails = TextEditingController();
TextEditingController password = TextEditingController();
final _formKey = GlobalKey<FormState>();
static final List<Logindata> _login = [];
final DatabaseService _databaseService = DatabaseService();
Future<List<Logindata>> _getLogin() async {
await _databaseService.verifyuser(email, pass).then((value) {
if (value) {
AlertDialog alert = AlertDialog(
title: const Text('Login successful!'),
content: const Text('Welcome!'),
actions: <Widget>[
TextButton(
onPressed: () => (Navigator.push(
context,
MaterialPageRoute(builder: (context) => const HomePage()),
)),
child: const Text('OK'),
),
],
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
} else {
AlertDialog alert = AlertDialog(
title: const Text('Error!'),
content: const Text('Wrong Email or Password'),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context, 'OK'),
child: const Text('OK'),
),
],
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
});
return _login;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SingleChildScrollView(
child: Column(
children: [
Container(
padding: EdgeInsets.all(10),
child: Form(
key: _formKey,
child: Column(
children: [
Text(
'BeFit:Fitness Activity Tracker Progress\n\n',
style: TextStyle(fontSize: 24),
textAlign: TextAlign.start,
),
Text(
'Welcome',
style: TextStyle(fontSize: 40),
textAlign: TextAlign.center,
),
SizedBox(
height: 30,
),
Container(
child: TextFormField(
controller: emails,
decoration: InputDecoration(
border: UnderlineInputBorder(
borderSide:
BorderSide(width: 1, color: Colors.grey)),
labelText: 'Email'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Email is required';
}
return null;
},
),
),
SizedBox(
height: 20,
),
Container(
child: TextFormField(
controller: password,
obscureText: true,
decoration: InputDecoration(
border: UnderlineInputBorder(
borderSide:
BorderSide(width: 1, color: Colors.grey)),
labelText: 'Password'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Password is required';
}
return null;
},
),
),
SizedBox(
height: 20,
),
Container(
width: MediaQuery.of(context).size.width,
height: 50,
child: FlatButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
email = emails.text;
pass = password.text;
_getLogin();
print(email);
print(pass);
print('success');
}
},
child: Text("Login"),
textColor: Colors.white,
color: Colors.deepPurple[400],
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(10)),
),
),
SizedBox(
height: 20,
),
Container(
child: Row(
children: <Widget>[
Text('Does not have account?'),
FlatButton(
textColor: Colors.deepPurpleAccent[100],
child: Text(
'Sign up',
style: TextStyle(fontSize: 16),
),
onPressed: () {
//signup screen
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SignUp()),
);
},
)
],
mainAxisAlignment: MainAxisAlignment.center,
))
],
),
),
)
],
),
),
),
);
}
}
Here is the error
enter image description here
I'm using this flutter to complete my project but there are some errors that I can't solve it. Sorry if my coding looks not right because still lacks in coding
Your verifyuser function does not return anything so your value returns null. You either need to return something or check for null values in your then statement.
Future<String> verifyuser(String user, String pass)async {
return user + pass;
}

flutter app , Unhandled Exception: Null check operator used on a null value

This is a simple flutter app. I am getting this error on my signup page which connects to firebase.
when i try to sign up, it remains on thinking with ⭕ spinning, i am getting this error in the debug console:
VERBOSE-2:ui_dart_state.cc(198)] Unhandled Exception: Null check operator used on a null value
#0 _SignupScreenState.signUpUser package:instagram_flutter/screens/signup_screen.dart:5
any thoughts?
here is the code that I believe is the source of the problem at:
(_image != null
? CircleAvatar
This is that block of code:
Stack(
children: [
_image != null
? CircleAvatar(
radius: 32,
backgroundImage: MemoryImage(_image!),
backgroundColor: Colors.red,
)
: const CircleAvatar(
radius: 32,
backgroundImage: NetworkImage(
'https://i.stack.imgur.com/l60Hf.png'),
backgroundColor: Colors.red,
),
I am new to coding and flutter, what should I put to replace the "?"
here is the entire code for the sign_up_screen (it is taken from a tutorial):
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:image_picker/image_picker.dart';
import 'package:instagram_flutter/resources/auth_methods.dart';
import 'package:instagram_flutter/responsive/mobile_screen_layout.dart';
import 'package:instagram_flutter/responsive/web_screen_layout.dart';
import 'package:instagram_flutter/screens/login_screen.dart';
import 'package:instagram_flutter/utils/colors.dart';
import 'package:instagram_flutter/utils/utils.dart';
import '../responsive/responsive_layout_screen.dart';
import '../widgets/text_field_input.dart';
class SignupScreen extends StatefulWidget {
const SignupScreen({Key? key}) : super(key: key);
#override
_SignupScreenState createState() => _SignupScreenState();
}
class _SignupScreenState extends State<SignupScreen> {
final TextEditingController _usernameController = TextEditingController();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final TextEditingController _bioController = TextEditingController();
bool _isLoading = false;
Uint8List? _image;
#override
void dispose() {
super.dispose();
_emailController.dispose();
_passwordController.dispose();
_usernameController.dispose();
}
void signUpUser() async {
// set loading to true
setState(() {
_isLoading = true;
});
// signup user using our authmethodds
String res = await AuthMethods().signUpUser(
email: _emailController.text,
password: _passwordController.text,
username: _usernameController.text,
bio: _bioController.text,
file: _image!);
// if string returned is sucess, user has been created
if (res == "success") {
setState(() {
_isLoading = false;
});
// navigate to the home screen
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => const ResponsiveLayout(
mobileScreenLayout: MobileScreenLayout(),
webScreenLayout: WebScreenLayout(),
),
),
);
} else {
setState(() {
_isLoading = false;
});
// show the error
showSnackBar(context, res);
}
}
selectImage() async {
Uint8List im = await pickImage(ImageSource.gallery);
// set state because we need to display the image we selected on the circle avatar
setState(() {
_image = im;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: SafeArea(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 32),
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Flexible(
child: Container(),
flex: 2,
),
SvgPicture.asset(
'assets/ic_instagram.svg',
color: primaryColor,
height: 64,
),
const SizedBox(
height: 64,
),
Stack(
children: [
_image != null
? CircleAvatar(
radius: 64,
backgroundImage: MemoryImage(_image!),
backgroundColor: Colors.red,
)
: const CircleAvatar(
radius: 64,
backgroundImage: NetworkImage(
'https://i.stack.imgur.com/l60Hf.png'),
backgroundColor: Colors.red,
),
Positioned(
bottom: -10,
left: 80,
child: IconButton(
onPressed: selectImage,
icon: const Icon(Icons.add_a_photo),
),
)
],
),
const SizedBox(
height: 24,
),
TextFieldInput(
hintText: 'Enter your username',
textInputType: TextInputType.text,
textEditingController: _usernameController,
),
const SizedBox(
height: 24,
),
TextFieldInput(
hintText: 'Enter your email',
textInputType: TextInputType.emailAddress,
textEditingController: _emailController,
),
const SizedBox(
height: 24,
),
TextFieldInput(
hintText: 'Enter your password',
textInputType: TextInputType.text,
textEditingController: _passwordController,
isPass: true,
),
const SizedBox(
height: 24,
),
TextFieldInput(
hintText: 'Enter your bio',
textInputType: TextInputType.text,
textEditingController: _bioController,
),
const SizedBox(
height: 24,
),
InkWell(
child: Container(
child: !_isLoading
? const Text(
'Sign up',
)
: const CircularProgressIndicator(
color: primaryColor,
),
width: double.infinity,
alignment: Alignment.center,
padding: const EdgeInsets.symmetric(vertical: 12),
decoration: const ShapeDecoration(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
),
color: blueColor,
),
),
onTap: signUpUser,
),
const SizedBox(
height: 12,
),
Flexible(
child: Container(),
flex: 2,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
child: const Text(
'Already have an account?',
),
padding: const EdgeInsets.symmetric(vertical: 8),
),
GestureDetector(
onTap: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const LoginScreen(),
),
),
child: Container(
child: const Text(
' Login.',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
padding: const EdgeInsets.symmetric(vertical: 8),
),
),
],
),
],
),
),
),
);
}
}
there is also the auth page, which includes a warning regarding
file != null) {:
the warning says:
The operand can't be null, so the condition is always true.
Remove the condition.dartunnecessary_null_comparison
auth_methods.dart:
import 'dart:typed_data';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:instagram_flutter/resources/storage_methods.dart';
class AuthMethods {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final FirebaseAuth _auth = FirebaseAuth.instance;
//sign up user
Future<String> signUpUser({
required String email,
required String password,
required String username,
required String bio,
required Uint8List file,
}) async {
String res = "Some error Occurred";
try {
if (email.isNotEmpty ||
password.isNotEmpty ||
username.isNotEmpty ||
bio.isNotEmpty ||
file != null) {
// registering user in auth with email and password
UserCredential cred = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
String photoUrl = await StorageMethods()
.uploadImageToStorage('profilePics', file, false);
await _firestore.collection('users').doc(cred.user!.uid).set({
'username': username,
'uid': cred.user!.uid,
'email': email,
'bio': bio,
'followers': [],
'following': [],
'photoUrl': photoUrl,
});
res = "success";
} else {
res = "Please enter all the fields";
}
} catch (err) {
return err.toString();
}
return res;
}
// logging in user
Future<String> loginUser({
required String email,
required String password,
}) async {
String res = "Some error Occurred";
try {
if (email.isNotEmpty || password.isNotEmpty) {
// logging in user with email and password
await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
res = "success";
} else {
res = "Please enter all the fields";
}
} catch (err) {
return err.toString();
}
return res;
}
Future<void> signOut() async {
await _auth.signOut();
}
}
Make sure that the declaration for _image is of type MemoryImage like this: MemoryImage? _image; Then, when using the value for the background image, just use _image, not MemoryImage(_image!).
Try using this way..
Stack(
children: [
_image == null
? const CircleAvatar(
radius: 32,
backgroundImage: NetworkImage(
'https://i.stack.imgur.com/l60Hf.png'),
backgroundColor: Colors.red,
):
CircleAvatar(
radius: 32,
backgroundImage: MemoryImage(_image),
backgroundColor: Colors.red,
),
On your signUpUser you are directly using bang! without checking null.
Here
// signup user using our authmethodds
...
file: _image!);
Try
void signUpUser() async {
if (_image == null) {
debugPrint("got null on _image");
_isLoading = false;
return;
}
And everything seems ok on Stack

Flutter Integration test case fails when run

I'm trying to run an integration test in my app. The screen is my login screen which leads to a signup flow and logged in to Home Screen. I'm using flutter integration test from the framework it self.
I've tried to run an integration test on the login screen but I get this error,
The following TestFailure object was thrown running a test:
Expected: exactly one matching node in the widget tree
Actual: _WidgetPredicateFinder:<zero widgets with widget matching predicate (Closure: (Widget) =>
bool) (ignoring offstage widgets)>
Which: means none were found but one was expected
My Login screen looks like this
class LoginScreen extends StatefulWidget {
static String tag = loginScreenRoute;
const LoginScreen({Key? key}) : super(key: key);
#override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _userLoginFormKey = GlobalKey<FormState>();
String? _userName = "";
String? _password = "";
bool _invisiblePass = false;
TextEditingController usernameController = TextEditingController();
TextEditingController passwordController = TextEditingController();
bool hasInterNetConnection = false;
late StreamSubscription _connectionChangeStream;
#override
initState() {
//Create instance
ConnectionUtil connectionStatus = ConnectionUtil.getInstance();
//Initialize
connectionStatus.initialize();
//Listen for connection change
_connectionChangeStream =
connectionStatus.connectionChange.listen(connectionChanged);
super.initState();
}
#override
void dispose() {
_connectionChangeStream.cancel();
super.dispose();
}
void connectionChanged(dynamic hasConnection) {
setState(() {
hasInterNetConnection = hasConnection;
//print(isOffline);
});
if (!hasInterNetConnection) {
offlineBar(context);
}
}
final loading = Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
CircularProgressIndicator(
color: lightWTextColor,
),
Text(" Login in ... Please wait")
],
);
void _showPassword() {
setState(() {
_invisiblePass = !_invisiblePass;
});
}
#override
Widget build(BuildContext context) {
//// user email ////
TextFormField userName() => TextFormField(
key: const Key('login username input'),
autofocus: false,
keyboardType: TextInputType.emailAddress,
controller: usernameController,
validator: validateEmail,
onSaved: (value) => _userName = value!.trim(),
textInputAction: TextInputAction.next,
style: AppTheme.body1WTextStyle,
decoration: buildInputDecoration(
'Enter Email',
Icons.email,
lightWTextColor.withOpacity(0.4),
),
// focusNode: _usernameFocusNode,
// onFieldSubmitted: (String val) {
// final focusNode = FocusNode();
// focusNode.unfocus();
// },
);
//// user password ////
TextFormField userPassword() => TextFormField(
key: const Key('login password input'),
obscureText: !_invisiblePass,
keyboardType: TextInputType.visiblePassword,
controller: passwordController,
validator: validatePassword,
onSaved: (value) => _password = value!.trim(),
textInputAction: TextInputAction.done,
style: AppTheme.body1WTextStyle,
decoration: buildInputDecoration(
'Enter Password',
Icons.vpn_lock,
lightWTextColor.withOpacity(0.4),
).copyWith(
suffixIcon: GestureDetector(
onTap: () {
_showPassword();
},
child: Icon(
_invisiblePass ? Icons.visibility : Icons.visibility_off,
color: Colors.black54,
),
),
),
);
final forgotLabel = Padding(
padding: const EdgeInsets.all(0.0),
child: Container(
alignment: Alignment.topRight,
child: TextButton(
child: const Text(
"Forgot password?",
style: AppTheme.body1WTextStyle,
),
onPressed: () {
Navigator.of(context).pushNamed(passwordResetScreenRoute);
},
),
),
);
final signupLabel = Padding(
padding: const EdgeInsets.all(10.0),
child: TextButton(
child: const Text(
"Sign Up for an Account",
style: AppTheme.subTitleWTextStyle,
),
onPressed: () {
Navigator.of(context).pushNamed(
userEditScreenRoute,
arguments: eProfile.addProfile,
);
},
),
);
final loginButton = ButtonWidget(
key: const Key('login button'),
text: 'LOG IN',
btnColor: accentColor,
borderColor: accentColor,
textColor: lightWTextColor,
onPressed: () {
Navigator.of(context).pushReplacementNamed(homeScreenRoute);
// _submit();
},
);
final loginForm = Form(
key: _userLoginFormKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
userName(),
const SizedBox(
height: 10.0,
),
userPassword(),
forgotLabel,
const SizedBox(
height: 10.0,
),
loginButton,
const SizedBox(
height: 10.0,
),
signupLabel,
],
),
);
final mainBody = InkWell(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
decoration: wBackground(),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'assets/images/_logo.png',
height: 200.0,
),
Expanded(
flex: 1,
child: loginForm, //Text('this text here'),
),
],
),
),
),
),
);
return SafeArea(
child: Scaffold(
body: SingleChildScrollView(
child: mainBody,
),
),
);
}
}
and when I try to navigate to Home Screen on tap of login button, the test fails.
my test case is like this
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
//
// start.main();
login.main();
}
//
void main() {
doLoginTest();
}
void doLoginTest() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets("Login in test run", (WidgetTester tester) async {
//
pawfect.main();
await tester.pumpAndSettle(const Duration(seconds: 3));
//test here
final Finder login =
find.byWidgetPredicate((widget) => widget is LoginScreen);
expect(login, findsOneWidget);
await tester.pumpAndSettle(const Duration(seconds: 1));
//
var emailInput = find.byKey(const Key('login username input'));
await tester.tap(emailInput);
await tester.enterText(emailInput, "test#m.com");
await tester.pumpAndSettle(const Duration(seconds: 1));
//
var passwordInput = find.byKey(const Key('login password input'));
await tester.tap(passwordInput);
await tester.enterText(passwordInput, "password");
await tester.pumpAndSettle(const Duration(seconds: 1));
//
var loginButton = find.byKey(const Key('login button'));
await tester.tap(loginButton, warnIfMissed: false);
await tester.pumpAndSettle(const Duration(seconds: 3));
//
// expect(version, findsOneWidget);
// final Finder home = find.byWidget(const HomeScreen());
expect(find.byWidgetPredicate((widget) => widget is HomeScreen),
findsOneWidget);
// await tester.pumpAndSettle(const Duration(seconds: 1));
var version = find.byWidgetPredicate(
(widget) => widget is Text && widget.data!.contains("Version: 2.0"));
expect(version, findsOneWidget);
await tester.pumpAndSettle(const Duration(seconds: 3));
});
}
what am I doing wrong here? I tried to look for something helpful over the internet and in the docs but I couldn't get my hands dirty enough. Will someone please help me to write a fine Integration test move in with screen to another screen. Thank you so much in advance.
Do you still have both main methods in your test file? If so can you remove the first (I don't understand how that can even be there):
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
//
// start.main();
login.main();
}
Also try stepping through your code - add a breakpoint in your test file and with that test file still in the editor press F5 ( I am assuming here you are in VSCode like me ), find out which expect call is reporting the failure - I'm guessing it is the second:
expect(find.byWidgetPredicate((widget) => widget is HomeScreen),
findsOneWidget);
Try adding this code before that call (instead of your existing pumpAndSettle call):
await tester.pump(const Duration(milliseconds: 4000));
await tester.pumpAndSettle();
Also consider some the ideas in this answer: https://stackoverflow.com/a/70472212/491739

type 'Future<dynamic>' is not a subtype of type '() => void' flutter

════════ Exception caught by widgets library ═══════════════════════════════════
The following _TypeError was thrown building ProfileEdit(dirty, state: _ProfileEditState#eb2ff):
type 'Future' is not a subtype of type '() => void'
Please let me know where did I went wrong, I am new to Flutter.
Can you help with the subject?
class ProfileEdit extends StatefulWidget {
final Users profile;
const ProfileEdit({Key key, this.profile}) : super(key: key);
#override
_ProfileEditState createState() => _ProfileEditState();
}
class _ProfileEditState extends State<ProfileEdit> {
var _formKey = GlobalKey<FormState>();
String _userName;
File _valuePhoto;
bool _loading = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.grey,
title: Text(
"Profili Düzenle",
style: TextStyle(color: Colors.black),
),
leading: IconButton(
icon: Icon(
Icons.close,
color: Colors.black,
),
onPressed: () => Navigator.pop(context)),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.check,
color: Colors.black,
),
onPressed: _save()),
],
),
body: ListView(
children: <Widget>[
_loading
? LinearProgressIndicator()
: SizedBox(
height: 0.0,
),
_profilePhoto(),
_userInfo(),
],
),
);
}
_save() async {
if (_formKey.currentState.validate()) {
setState(() {
_loading = true;
});
_formKey.currentState.save();
String profilePhotoUrl;
if (_valuePhoto == null) {
profilePhotoUrl = widget.profile.photoUrl;
} else {
profilePhotoUrl = await StorageService().profilePhotoAdd(_valuePhoto);
}
String activeUserId =
Provider.of<AuthorizationService>(context, listen: false)
.activeUserId;
//veritabanına güncel verileri eklemek için.
FireStoreService().userUpdate(
userId: activeUserId, userName: _userName, photoUrl: profilePhotoUrl);
setState(() {
_loading = false;
});
Navigator.pop(context);
}
}
_profilePhoto() {
return Padding(
padding: const EdgeInsets.only(top: 15.0, bottom: 20.0),
child: Center(
child: InkWell(
onTap: _galleryChoose,
child: CircleAvatar(
backgroundColor: Colors.grey,
backgroundImage: _valuePhoto == null
? NetworkImage(widget.profile.photoUrl)
: FileImage(_valuePhoto), //galeriden fotoğraf ekleme.
radius: 55.0,
),
),
),
);
}
_galleryChoose() async {
var image = await ImagePicker().getImage(
source: ImageSource.gallery,
maxWidth: 800,
maxHeight: 600,
imageQuality: 80);
setState(() {
_valuePhoto = File(image.path);
});
}
_userInfo() {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 120.0,
),
child: Form(
child: Column(
children: <Widget>[
SizedBox(
height: 20.0,
),
TextFormField(
//varsayılan kullanıcı adı düzenleme ekranında da gözükmesi için initialvalue çalışıyor.
initialValue: widget.profile.userName,
decoration: InputDecoration(labelText: "Kullanıcı Adı"),
validator: (inputValue) {
return inputValue.trim().length <= 3
? "Kullanıcı Adı en az 4 karakter olmalı."
: null;
},
onSaved: (inputValue) {
_userName = inputValue;
},
),
],
),
),
);
}
}
instead of
_save() async {
try using
Future _save() async {
The onPressed property of a button needs a function that has a return type of void, and every function that is marked as async will always have a return type of some kind of Future. To get around this, you can wrap passing _save to the button in a lambda function:
onPressed: () => _save(),

Flutter: Multiple Instances of Shared Preferences?

I am having a problem with SharedPreferences and multiple Modules I am generating on a Form using ListView.builder
The form is basically asking for some parents details and their childs details - by default the form assumes the parent has one child, but more can be added by clicking a button. The ChildModule has the ability to "close" but when "re-opened" the data doesn't persist, hence using SharedPreferences, it works fine with one Child, but once a second child is added it seems to be creating multiple Instances of SharedPreferences.
I have cut out everything to show what I am trying to achieve. NOTE this is being used as a Web App if it matters.
Oh and ChildModule needs to have its own state because it has a widget which requires it (not shown)
ENQUIRY FORM
final GlobalKey<FormBuilderState> _enquiryFormKey = GlobalKey<FormBuilderState>();
class EnquiryForm extends StatefulWidget {
static List<int> numberOfChildren = [1];
#override
_EnquiryFormState createState() => _EnquiryFormState();
}
class _EnquiryFormState extends State<EnquiryForm> {
int defaultNumberOfChildren = 1;
removeModule(){
setState(() {});
}
#override
Widget build(BuildContext context) {
return FormBuilder(
key: _enquiryFormKey,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: CustomTextField(
label: 'Parent First Name',
isRequired: true,
),
),
),
//ChildModuleList
ListView.builder(
shrinkWrap: true,
itemCount: EnquiryForm.numberOfChildren.length,
itemBuilder: (context,int index){
return ChildModule(EnquiryForm.numberOfChildren[index], removeModule);
}
),
SizedBox(height: 20,),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
ThemedButton(
onPressed: (){
setState(() {
defaultNumberOfChildren++;
EnquiryForm.numberOfChildren.add(defaultNumberOfChildren);
});
},
child: Text(
'Add Additional Child',
style: TextStyle(color: Colors.white),)
),
SizedBox(width: 10,),
ThemedButton(
onPressed: (){},
child: Text('Enquire Now', style: TextStyle(color: Colors.white),))
],
)
],
));
}
}
CHILD MODULE
class ChildModule extends StatefulWidget {
final int number;
final Function() callback;
ChildModule(this.number,this.callback);
#override
_ChildModule createState() => _ChildModule();
}
class _ChildModule extends State<ChildModule> {
SharedPreferences childModuleData;
String firstName;
bool loading = true;
bool isOpen;
#override
void initState() {
print('this module number is ${widget.number}');
_spInstance();
isOpen = true;
super.initState();
}
Future<void> _spInstance() async {
if(childModuleData == null && widget.number == 1) {
childModuleData = await SharedPreferences.getInstance();
print('got instance');
} else {
print('broken');
print(childModuleData);
};
String _testValue = childModuleData.getString('Child First Name');
if(_testValue == null){
childModuleData.setString('Child First Name', '');
loading = false;
} else {
childModuleData.clear();
_spInstance();
}
}
#override
Widget build(BuildContext context) {
return loading ? Loading() : Column(
children: <Widget>[
GestureDetector(
onTap: () {
setState(() {
if (isOpen == false) {
isOpen = true;
} else {
isOpen = false;
}
});
},
child: Container(
height: 40,
padding: EdgeInsets.only(left: 10, right: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
color: Colors.blue[50],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'Child Details',
style: TextStyle(color: Colors.blue[300], fontSize: 16),
),
Row(
children: <Widget>[
isOpen
? Icon(
Icons.arrow_drop_down,
size: 30,
)
: Transform.rotate(
angle: math.pi / 2,
child: Icon(
Icons.arrow_drop_down,
size: 30,
),
),
widget.number > 1
? IconButton(icon: Icon(Icons.clear), onPressed: () async {
await FormFunctions().removeModule(widget.number, EnquiryForm.numberOfChildren);
widget.callback();
})
: Container(),
],
),
],
),
),
),
AnimatedContainer(
duration: Duration(seconds: 2),
curve: Curves.fastOutSlowIn,
padding: EdgeInsets.fromLTRB(10, 5, 10, 5),
height: isOpen ? null : 0,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey[300]),
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
CustomTextField(
label: fieldFirstName,
isRequired: true,
initalValue: childModuleData.getString(fieldFirstName) ?? '',
onChanged: (value){
childModuleData.setString(fieldFirstName, value);
},
),
],
),
],
),
),
],
);
}
}
CONSOLE ERROR AFTER SECOND MODULE IS CREATED
Launching lib/main.dart on Chrome in debug mode...
Syncing files to device Chrome...
Debug service listening on ws://127.0.0.1:58490/EkMAy9CGY74=
Debug service listening on ws://127.0.0.1:58490/EkMAy9CGY74=
this module number is 1
got instance
Instance of 'SharedPreferences'
null
this module number is 2 //Number 2 Module is created
broken
null
null
TypeError: Cannot read property 'getString' of null
at child_module._ChildModule.new._spInstance$ (http://localhost:58433/packages/webenrol/shared/widgets/day_button.dart.lib.js:3704:47)
at _spInstance$.next (<anonymous>)
at runBody (http://localhost:58433/dart_sdk.js:43121:34)
at Object._async [as async] (http://localhost:58433/dart_sdk.js:43149:7)
at child_module._ChildModule.new.[_spInstance] (http://localhost:58433/packages/webenrol/shared/widgets/day_button.dart.lib.js:3694:20)
at child_module._ChildModule.new.initState (http://localhost:58433/packages/webenrol/shared/widgets/day_button.dart.lib.js:3689:24)
at framework.StatefulElement.new.[_firstBuild] (http://localhost:58433/packages/flutter/src/widgets/widget_span.dart.lib.js:41219:58)
at framework.StatefulElement.new.mount (http://localhost:58433/packages/flutter/src/widgets/widget_span.dart.lib.js:12605:24)
at framework.SingleChildRenderObjectElement.new.inflateWidget (http://localhost:58433/packages/flutter/src/widgets/widget_span.dart.lib.js:11420:16)
in your case the concern is at the level of recording data in shared preferences. one solution would be to add the widget number in the key to save like this (await SharedPreferences.getInstance()).setString("Your Key${widgetNumber}");
and edit your function _spInstance
class ChildModule extends StatefulWidget {
final int number;
final Function() callback;
ChildModule(this.number,this.callback);
#override
_ChildModule createState() => _ChildModule();
}
class _ChildModule extends State<ChildModule> {
SharedPreferences childModuleData;
...
Future<void> _spInstance() async {
if(childModuleData == null) {
childModuleData = await SharedPreferences.getInstance();
print('got instance');
}
String _testValue = childModuleData.getString('Child First Name${widget.number}');
//NB: do not clear data on chlidModuleData any more.
...
}
...
}