Google search engine
Home Blog Page 56

Flutter Performance Optimization

Ever wondered how flutter handles all your UI building and events like Futures, taps, etc.. on a single thread( yes it does all that on a single thread 😮😮😮 until and unless explicitly done).

What is Thread/Isolates ?

Thread is an independent process that has its own chunk of memory and executes the given instructions on that memory , It can work parallelly with other threads hence can reduce execution time of multiple process on a single thread .

Let’s understand this with an example :

In Fps games like counter strike, Call of duty, etc. you can see that as soon as you fire a weapon few tasks executes simultaneously like playing of bullet sound, change of bullet count and reduction in opponent health , All these things happens parallelly these are basically threads which execute parallelly and execute their task on separate isolates(isolates and threads can be used interchangeably as isolate is a Dart way of multi threading more on that below) which have its own memory.

Languages like JAVA and C++ Share Their heap memory with threads, but in case of flutter, every isolate has its own memory and works independently. As it has its own private space this memory doesn’t require locking, as if a thread finishes its task it already means that the thread has finished utilizing its memory space and then that memory can go for garbage collection.

To maintain these benefits flutter has a separate memory for every isolate(Flutter way of multi-threading) that’s why they are called isolate 🙂.

Learn more about isolates below.

How can it be helpful to me and where should I use isolates/Threads?

When to use isolates/threads ?

There are a few situations where isolates can be very handy.

  1. Let say you want to execute a network call and you want to process that data that you just received . and that data contains about million records that alone will hang your UI.
  2. You have some image processing tasks that you want to do on-device these kinds of tasks are highly computational as they have to deal with lots of number crunching operations which may lead to frozen UI or legginess in UI.

So to conclude when to use isolates, We should use them whenever you think there is a lot of computation that needs to be offloaded from the main thread.

How to use isolates ?

Flutter team has designed a very elegant and abstract way of using isolates/threads in a flutter, Using compute we can do the same task which isolates does but in a more cleaner and abstract way. Let’s take a look at the flutter compute function.

Syntax:

var getData = await compute(function,parameter);

Compute function takes two parameters :

  1. A future or a function but that must be static (as in dart threads does not share memory so they are class level members not object level).
  2. Argument to pass into the function, To send multiple arguments you can pass it as a map(as it only supports single argument).

compute function returns a Future which if you want can store into a variable and can provide it into a future builder.

Let’s start by analyzing a sample problem:

/media/247dce48c8ac87e5b91b48cd11740086

In the above code pausefunction() is called just below the build method which pauses the execution of code for 10 seconds. And because of that when you try to navigate to this page from a previous one there will be a delay of ten seconds before our page gets pushed on to the widget tree.

We can try to resolve this issue by using async.

https://gist.github.com/702x/24a798189ac096e688f8301f0e2381f2#file-with10seconddelay-dart

As you can see now we have declared our pause function as async even doing this will not help

As async in dart is basically puts our code in ideal until there is something to compute so it seems to us that dart is executing these on a different thread but actually it’s just waiting for some event to occur in that async function.

More on async below :

https://gist.github.com/702x/b50dba38b3aae2e592bd26e2a94a1da5#file-with10seconddelayasync-dart

Let’s solve the above issue using compute.

In the above code, we basically passed our function in compute() function and that creates a separate isolate to handle the task and our main UI will still run without any delay (check the debug console for response ).

Summary:

  1. Dart is by default executes all its code on a single-threaded.
  2. Every function and every async-await calls work only on the main thread(until and unless specified).
  3. We can create multiple threads using compute( Future function/normal function, argument).
  4. You can use compute for executing network calls, performing number-crunching calculations, image processing, etc.

This is all about compute to learn more about isolates (the underlying architecture of computing function) check out isolate .

Thanks for reading this article.

If you find it interesting Please Clap! and if you found anything wrong please let me know I would appreciate it for your contribution.

Check out full code at FlutterDevs GitHub.


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.

Related: Improving Scrolling Performance in Flutter: ListView, Slivers & Viewport Optimization

Need expert help building your Flutter app? Talk to FlutterExperts for architecture, development, and consulting support.

Twitter Authentication In Flutter

0

Demo module :

Introduction

In this blog, we shall discuss user authentication using firebase in flutter. We will learn authentication using twitter, email, and password, anonymous methods.


Table of content

: Connecting app to firebase

: Installing required package

: Anonymous auth

: Authentication using Email and Password

: Authentication using Twitter


Connecting app to firebase

  1. Open firebase, click on get started which will take you to the Add Project screen.
  2. Enter the project name and complete the other essential steps. It will take you to your project screen, click on the android icon.
  3. Now the steps which are coming are very important so please do them very carefully. You have to enter the package name which is generally your application Id in your app-level build.gradle file. Add the other two optional fields if you wish to add them as well.
  4. Now download the google-services.json. Move the downloaded google-serivces.json file into your Android app module root directory. (NOTE: Please check the file that you have downloaded has a google-services.json name or not because if you download it more then one time the name of the file changes to google-services(2).json(for example), so please remove (2) from the file name or rename it to google-services.json)
  5. You will see the following screen.

Here the first block contains the classpath that you have to add into your project level build.gradle file under the dependencies section. The second section contains a plugin and dependencies that you have to add it into your project app-level build.gradle file. Please add these lines properly and carefully if you are adding them for the first time.

Left: project/build.gradle ….Right :project/app/build.gradle

6. Now you should restart your application (NOTE: Please refer full restart not hot reload). Wait for few seconds and your application will be successfully added with firebase. If you see the bellow screen on your firebase then you have successfully added firebase to your app…

Congratulation…

Installing the required package

Update your pubspec.yaml with the following dependency.

flutter_twitter_login | Flutter Package
A Flutter plugin for using the native TwitterKit SDKs on Android and iOS. This plugin uses the new Gradle 4.1 and…pub.dev

firebase_auth | Flutter Package
A Flutter plugin to use the Firebase Authentication API. For Flutter plugins for other Firebase products, see…pub.dev

dependencies:
flutter:
sdk: flutter
firebase_auth: ^latets version
flutter_twitter_login:

Anonymous auth

: Go to the authentication tab in the Firebase console then enable anonymous authentication from the Sign-In Option.

: Sign In Function

Future<void> _signInAnonymously() async {
try {
await FirebaseAuth.instance.signInAnonymously();
} catch (e) {
print(e);
}
}

Try: contains code that may throw an exception.

Catch: used to handle an exception.

This method calls the FirebaseAuth.instance.signInAnonymously() ,return a user.

: Sign Out Function

Future<void> _signOut() async {
try {
await FirebaseAuth.instance.signOut();
} catch (e) {
print(e);
}
}

This method triggers the signOut method to signOut the user.


Authentication using Email and Password

: Setting up the variables

final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final FirebaseAuth _auth = FirebaseAuth.instance;

NOTE: FirebaseAuth is the entry point of the FirebaseAuthenticationSDK.

: Sign In Function

void _signInWithEmailAndPassword() async {
await _auth.signInWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
);
}

signInWithEmailAndPassword() method sign in a user with the given email address and password.

If sign In successful, it also signs the user in into the app and updates
the
onAuthStateChanged stream.

If sign In is unsuccessful, it shows three types of error:-

  1. ERROR_WEAK_PASSWORD: If the password is not strong enough.
  2. ERROR_INVALID_EMAIL: If the email address is malformed.
  3. ERROR_EMAIL_ALREADY_IN_USE: If the email is already in use by a different account.

: Sign Up Function

_signUpWithEmailAndPassword() async {
await _auth.createUserWithEmailAndPassword(
email: _emailController.text, password: _passwordController.text);
}

createUserWithEmailAndPassword() create a new user account with the given email address and password.

If successful, it also signs the user into the app and updates the onAuthStateChanged stream.

You must enable Email & Password accounts in the Auth section of the Firebase console before being able to use them.

If sign In is unsuccessful, it show error:-

  1. ERROR_INVALID_EMAIL — If the [email] address is malformed.
  2. ERROR_WRONG_PASSWORD — If the [password] is wrong.
  3. ERROR_USER_NOT_FOUND — If there is no user corresponding to the given [email] address, or if the user has been deleted.
  4. ERROR_USER_DISABLED — If the user has been disabled (for example, in the Firebase console)
  5. ERROR_TOO_MANY_REQUESTS — If there were too many attempts to sign in as this user.
  6. ERROR_OPERATION_NOT_ALLOWED — Indicates that Email & Password accounts are not enabled.

: Sign Out Function

_logOut() async {
try {
await _auth.signOut();
Navigator.of(context).pop();
} catch (error) {
print(error);
}
}

signOut() method Signs out the current user and clears it from the disk cache.

If successful, it signs the user out of the app and updates the onAuthStateChanged stream.

: Reset Password Function

_resetPassword() async {
try {
_auth.sendPasswordResetEmail(email: email);
} catch (error) {
print(error);
}
}

sendPasswordResetEmail() method triggers the Firebase Authentication backend to send a password reset email to the given email address, which must correspond to an existing user of your app.

If it is unsuccessful then it gives error:

  1. ERROR_INVALID_EMAIL — If the email address is malformed.
  2. ERROR_USER_NOT_FOUND — If there is no user corresponding to the given email address.

Authentication using Twitter

Setting up the Project

  1. Plugin Used

flutter_twitter | Flutter Package
A Flutter plugin for using the native TwitterKit SDKs on Android and iOS. This plugin uses the new Gradle 4.1 and…pub.dev

2. Go to https://apps.twitter.com/ and make a developer account.

NOTE: Do not forget to add the callback URLs. You need to add three callback URL

  • for android:twittersdk: //,
  • for ios: twitterkit-CONSUMERKEY: //
  • add the URL that you get while enabling the twitter authentication from firebase.

You can add URL only for ios or for android.

3. Enable twitter sign-in option in the firebase console. (Paste the consumerKey, consumerSecret in the API key and API secret section respectively)

3. Click enable

We are now ready to go

: FirebaseAuth instance

Let’s create a firebase auth instance.

FirebaseAuth _auth = FirebaseAuth.instance;

: TwitterLogin

flutter_twitter_login provides us TwitterLogin class that takes consumerKey and consumerSecret that we got during creating the twitter developer account.

final TwitterLogin twitterLogin = new TwitterLogin(
consumerKey: 'YOUR CONSUMERKEY',
consumerSecret: 'YOUR SECRETKEY',
);

: Sign In Function

void _signInWithTwitter(String token, String secret) async {
final AuthCredential credential = TwitterAuthProvider.getCredential(
authToken: token, authTokenSecret: secret);
await _auth.signInWithCredential(credential);
}

: Logging in User

void _login() async {
final TwitterLoginResult result = await twitterLogin.authorize();
String newMessage;
if (result.status == TwitterLoginStatus.loggedIn) {
_signInWithTwitter(result.session.token, result.session.secret);
} else if (result.status == TwitterLoginStatus.cancelledByUser) {
newMessage = 'Login cancelled by user.';
} else {
newMessage = result.errorMessage;
}

setState(() {
message = newMessage;
});
}

: LogOut

void _logout() async {
await twitterLogin.logOut();
await _auth.signOut();
}

: Full code

import 'package:flutter/material.dart';
import 'package:flutter_twitter_login/flutter_twitter_login.dart';
import 'package:firebase_auth/firebase_auth.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: StreamBuilder(
stream: FirebaseAuth.instance.onAuthStateChanged,
builder: (ctx, userSnapshot) {
if (userSnapshot.hasData) {
return LogOut();
} else if (userSnapshot.hasError) {
return CircularProgressIndicator();
}
return SignInScreen();
},
),
);
}
}

class SignInScreen extends StatefulWidget {
@override
_SignInScreenState createState() => _SignInScreenState();
}

class _SignInScreenState extends State<SignInScreen> {
String message;

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network(
"https://www.3nions.com/wp-content/uploads/2020/01/comp_1.gif",
height: 200,
),
InkWell(
onTap: () {
_login();
},
borderRadius: BorderRadius.circular(30),
splashColor: Colors.blue,
child: Container(
height: 50,
width: 300,
child: Center(
child: Text(
"Sign In using twitter",
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold,
),
)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
border: Border.all(
color: Colors.blue,
width: 3,
)),
),
),
SizedBox(
height: 20,
),
Text(
message == null ? "" : message,
style: TextStyle(
color: Colors.red,
fontWeight: FontWeight.bold,
),
),
InkWell(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (_) {
return EmailPasswordScreen();
},
));
},
borderRadius: BorderRadius.circular(30),
splashColor: Colors.blue,
child: Container(
height: 50,
width: 300,
child: Center(
child: Text(
"Sign In using email and password",
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold,
),
)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
border: Border.all(
color: Colors.blue,
width: 3,
)),
),
),
SizedBox(
height: 40,
),
InkWell(
onTap: () {
_signInAnonymously();
},
borderRadius: BorderRadius.circular(30),
splashColor: Colors.blue,
child: Container(
height: 50,
width: 300,
child: Center(
child: Text(
"Sign In as anonymous user",
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold,
),
)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
border: Border.all(
color: Colors.blue,
width: 3,
)),
),
),
],
),
),
);
}

void _login() async {
final TwitterLoginResult result = await twitterLogin.authorize();
String newMessage;
if (result.status == TwitterLoginStatus.loggedIn) {
_signInWithTwitter(result.session.token, result.session.secret);
} else if (result.status == TwitterLoginStatus.cancelledByUser) {
newMessage = 'Login cancelled by user.';
} else {
newMessage = result.errorMessage;
}

setState(() {
message = newMessage;
});
}
}

final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
FirebaseAuth _auth = FirebaseAuth.instance;

final TwitterLogin twitterLogin = new TwitterLogin(
consumerKey: '',
consumerSecret: '',
);

void _signInWithTwitter(String token, String secret) async {
final AuthCredential credential = TwitterAuthProvider.getCredential(
authToken: token, authTokenSecret: secret);
await _auth.signInWithCredential(credential);
}

void _signInWithEmailAndPassword() async {
await _auth.signInWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
);
}

_signUpWithEmailAndPassword() async {
await _auth.createUserWithEmailAndPassword(
email: _emailController.text, password: _passwordController.text);
}

Future<void> _signInAnonymously() async {
try {
await FirebaseAuth.instance.signInAnonymously();
} catch (e) {
print(e);
}
}

_logout() async {
await twitterLogin.logOut();
await _auth.signOut();
}




class LogOut extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Auth Demo"),
),
body: FutureBuilder(
future: FirebaseAuth.instance.currentUser(),
builder: (context, snapshot) {
FirebaseUser firebaseUser = snapshot.data;
return snapshot.hasData
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"SignIn Success 😊",
style: TextStyle(
color: Colors.green,
fontWeight: FontWeight.bold,
fontSize: 30,
),
),
SizedBox(
height: 20,
),
Text("UserId: ${firebaseUser.uid}"),
SizedBox(
height: 20,
),
firebaseUser.photoUrl == null
? SizedBox(
height: 0,
)
: Image.network(
firebaseUser.photoUrl,
height: 100,
),
Text("Your name: ${firebaseUser.displayName}"),
Text("Your email: ${firebaseUser.email}"),
SizedBox(
height: 20,
),
RaisedButton(
onPressed: () {
_logout();
},
child: Text(
"LogOut",
style: TextStyle(color: Colors.white),
),
color: Colors.blue,
)
],
),
)
: CircularProgressIndicator();
},
),
);
}
}

class EmailPasswordScreen extends StatefulWidget {
@override
_EmailPasswordScreenState createState() => _EmailPasswordScreenState();
}

class _EmailPasswordScreenState extends State<EmailPasswordScreen> {
bool isSingIn = true;

@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Enter your email password",
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold,
fontSize: 25),
),
Card(
elevation: 5,
child: TextField(
controller: _emailController,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: "Email", prefixIcon: Icon(Icons.email)),
),
),
Card(
elevation: 5,
child: TextField(
controller: _passwordController,
decoration: InputDecoration(
hintText: "Password", prefixIcon: Icon(Icons.lock_outline)),
),
),
RaisedButton(
color: Colors.blue,
onPressed: () {
isSingIn
? _signInWithEmailAndPassword()
: _signUpWithEmailAndPassword();
Navigator.of(context).pop();
},
child: Text(
isSingIn ? "Sign In" : "Sign Up",
style: TextStyle(color: Colors.white),
),
),
FlatButton(
onPressed: () {
setState(() {
isSingIn = !isSingIn;
});
},
child: Text(
isSingIn ? "Create an account" : "Already have an account"))
],
),
),
);
}
}

: GitHub Link

flutter-devs/twitter_auth_demo
A new Flutter application. This project is a starting point for a Flutter application. A few resources to get you…github.com

: If you want to perform local authentication using fingerprint, you can read the my blog post on Local Authentication in Futter .

Local Authentication in Flutter
Local Authentication in Fluttermedium.com

Google Sign In With Flutter
Google sign-in with Flutter using Firebase authenticationmedium.com

Phone Authentication in Flutter
Building a phone number authentication flutter appmedium.com


Thanks for Reading this article ❤

If I got something wrong? Let me know in the comments. I would love to improve.

Clap 👏 If this article helps you.

If we got something wrong? Let me know in the comments. we would love to improve.


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.

Need expert help building your Flutter app? Talk to FlutterExperts for architecture, development, and consulting support.

Facebook Login In Flutter

0

Login has become one of the most important parts of lives for a developer by having a working on-boarding system we can help tend to users need better than ever. hence why it has become a necessity in almost all the apps.

Because of This most companies have brought out a way for users to login seamlessly through their own apps companies like Facebook, Google and Twitter have made it so that u can log in in 1 click, and with flutter, It has become even simpler to implement.


What you will need?

A couple of packages from pub.dev, enable Facebook for developers and Twitter for Developers.

Packages are:

flutter_facebook_login: ^latest version
 http: any

What we are going to do?

How to access the required data of user through Facebook

Before we can just start logging in there are a few steps that are required to do for logging in Facebook.

Facebook :

  1. So first of all you will have to enable Facebook for developers that is the only way for you to get access to your app ID and app secret, if you have a Facebook profile then it only takes a minute to do it.
  2. After making an account make an app in Facebook for developers after which you will get access to your app ID and app Secret (to reveal app secret go into settings then basic it should look like this:
All the information required to make the sign In happen is in here

3. Now that we have created Facebook for developer’s profiles and have gotten access to our secret key and app ID we can move over to Firebase project to take the necessary steps for log in.

4. Ok once you are at the firebase project you can go to Authentication and then select sign-in methods.

4. Select the Facebook option, it will ask for your App ID and App secret the one you got from Facebook for developers.

5. This will help you in Signing In with Facebook and after that you need to copy that O’auth http link cause it is very important(save it in a text file)

6. Now you will need to go to https://developers.facebook.com/docs/facebook-login/android, to take other actions that will enable you to Sign In through Facebook(Not much left just 3–4 more steps). Don’t worry we are here for full support and will guide you through them as well.

7. Since we are not working with native android we can actually skip many of those steps(GOD I LOVE HOW EASY FLUTTER MAKES EVERYTHING ELSE), we can start at step 1 and choose our project name(the one we just created in Facebook for developers. So go ahead and select it

Choose your app you want to enable facebook login for

8. After selecting it we can jump directly to step 5, now there you will need to provide your app’s package name and main activity name there you can find them if you go through your app-level module and opening src t find AndroidManifest.xml (the path is android/app/src/main/AndroidManifest.xml)

Enter your package name and main activity in both fields

9. Now we come to the part that took me the longest and was very troublesome (don’t worry I went through the pain so you guys don’t have to!), so we come to Step 6 where now we need to provide release key for this,

so the things you will need to generate a release are(unless you have your app published on Play Store you will get your release key in SHa1 from there but you will have to convert it to base64 which you can do by a simple google search)

A) openssl which u can get at https://code.google.com/archive/p/openssl-for-windows/downloads , after downloading it save it on your C: drive in a seperate folder and name it something like “open ssl”

B) you need to have jdk installed on your system to be able to generate the keys : https://www.oracle.com/java/technologies/javase-jdk13-downloads.html

After that you will need to open command line in jdk folder

(the path is C:\Program Files\Java\jdk1.8.0_261\bin), once opened you need to run this command :

  • keytool -exportcert -alias androiddebugkey -keystore “C:\Users\USERNAME\.android\debug.keystore” | “PATH_TO_OPENSSL_LIBRARY\bin\openssl” sha1 -binary | “PATH_TO_OPENSSL_LIBRARY\bin\openssl” base64

remember to fill in your own details in the command like your username and the path to open SSL (if you followed what I have said completely then it will be : “C:/open SSL/bin/OpenSSL” fill it in both places where it is required.

It will then generate the key required to for logging in to Facebook, it will be of 28 characters minimum and will end with an “=”

the release key should be added there

10. Now we are really close to completing our Facebook login all we need right now is to put our O’auth(remember this guy from step 5?), all you need to do now is go back to your Facebook for developers(the one where you created your app) and then you will see product + icon there click it.

after clicking on product and doing the additional steps you will have facebook login option there

After getting facebook login option there you can click it then select settings and then you will encounter this page:

See the censored part? That’s where you will have to put in your O’auth you got from Firebase(in case you didn’t save it you can go back and click on edit option in Firebase Sign in methods to get it again)

After that save changes.

11. Now we can finally move onto our project and add some configuration there as well

Go to your /android/app/src/main/res/values/ and find if you have a Strings.xml file if you dont have it create one, after creating one you can enter this information in it :

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Your App Name here.</string>

<!-- Replace "000000000000" with your Facebook App ID here. -->
<string name="facebook_app_id">YOUR APP ID HERE</string>

<!--
Replace "000000000000" with your Facebook App ID here.
**NOTE**: The scheme needs to start with `fb` and then your ID.
-->

<string name="fb_login_protocol_scheme">fbYOUR APP ID</string>
</resources>

DO as told in the comments.

Now go over to your <your project root>/android/app/src/main/AndroidManifest.xml and add the following just above the “<! — Don’t delete the meta-data below.” comment in androidManifest.xml file then add the following

<meta-data android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id"/>

<activity android:name="com.facebook.FacebookActivity"
android:configChanges=
"keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="@string/app_name" />

<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/fb_login_protocol_scheme" />
</intent-filter>
</activity>

After you are done with that part, you are almost good to go(there are some specific IOS configurations which you can find in https://pub.dev/packages/flutter_facebook_login be sure to do them as well if you want it to work for IOS as well)

Now in your project make a HelperClass called Authentication.dart

In the file you need to make a function that will help you sign the user into Facebook :

first of all import all these files

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_facebook_login/flutter_facebook_login.dart';
import 'package:flutter_twitter_login/flutter_twitter_login.dart';
import 'package:http/http.dart' as http;

After this make an object of FacebookLogin() and write the following function

final fbLogin = FacebookLogin();

Future signInFB() async {
final FacebookLoginResult result = await fbLogin.logIn(["email"]);
final String token = result.accessToken.token;
final response = await http.get('https://graph.facebook.com/v2.12/me?fields=name,first_name,last_name,email&access_token=${token}');
final profile = jsonDecode(response.body);
print(profile);

return profile;
}

After that, you can call that function in your button like

RaisedButton(
onPressed: () {
Authenticate auth = Authenticate();
auth.signInFB().whenComplete((onComplete) {Navigator.of(context}.push(MaterialPageRoute(builder: (context)=>HomePage()));
},

Its that simple.

Congratulations you have achieved Facebook login, now on your app after clicking on sign In FB button you will be redirected to Facebook page to allow sign in and after allowing in you can see it print users data which you can store in your database and then log them in.


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

Feel free to connect with us:
And read more articles from FlutterDevs.com

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences.

Related: SMS Using Twilio In Flutter

Related: Using SharedPreferences in Flutter

Need expert help building your Flutter app? Talk to FlutterExperts for architecture, development, and consulting support.

www.flutterdevs.com

Stateful & Stateless: A Doubt Clearing Session

As a flutter developer, you have at least once come across a question of how would you draw a line between Stateless and Stateful, either this question would have been thrown on you or it has hit your mind hard by self-realization. However, it does not matter from where you get stuck here but the main point is….. Do you have any answer to it ?

Of course in search of this mysterious question, you would find that self-proclaimed complete definition on google which is…

If a widget can change — when a user interacts with it, for example — it’s stateful. A stateless widget never changes. Icon , IconButton , and Text are examples of stateless widgets. … A widget’s state is stored in a State object, separating the widget’s state from its appearance.

But if you have ever been a part of a discussion or have appeared for an interview (like me) then you must be aware that the conversation over stateless and stateful does not end here.

whaaatttt… ???? yes, the conversation does not end here.

After giving this definition a question arrives if the stateless widget has a stateful child what it would be called? Does it become a stateful widget or how it manages itself?

So….In the layout, if we choose there can be different widgets like a container which we will select as a stateless widget and it’s child also a container but we will take as a stateful widget and when you would rebuild then the state will only affect stateful container so it does not matter if the parent widget is stateful or not if the child is a stateful widget.

Actually you can say

The only thing which makes them different is the ability to reload at the run time

But the conversation does not end here

so let’s take another definition to conquer the dilemma

The important thing to note here is at the core both Stateless and Stateful widgets behave the same. They rebuild every frame, the difference is the StatefulWidget has a State object which stores state data across frames and restores it.

If you are in doubt, then always remember this rule: If a widget changes (the user interacts with it, for example) it’s stateful. However, if a child is reacting to change, the containing parent can still be a Stateless widget if the parent doesn’t react to change.

That effort was from my side but a description is not fully completed until we don’t know the view of others so let’s have some thoughts :

In this video, a simple definition of stateful and stateless is given

Stateless is Data less and Stateful is Data full

In this video, things have described in some interesting way so first, you should know what is the state

State The state is the information that can read synchronously when the widget is built and might change during the lifetime of the widget and that state changing requirement defines if the widget is stateful or stateless.

Incidentally, the difference between the stateful and stateless widget is very limited, the stateless widget can only once on to the screen while a stateful widget can be drawn multiple times.

Which effectively means that the build function of the stateless widget can be called only once when the class is instantiated or an object is created while in stateful widget build function can be called multiple time during run time and it also states that the content in stateless is immutable while in stateful it is mutable.

The build(…) function of the StateLessWidget is called only ONCE. To redraw the StatelessWidget, we need to create a new instance of the Widget.

After reading that much of content now must b able to create your own analogy which might help you to create your own way of explaining things completely with ease.

Introduction to widgets
Flutter widgets are built using a modern framework that takes inspiration from React. The central idea is that you…flutter.dev

Summary

So this was the discussion that could help you to find your at the stage where at least you can have an explanation for the question which is generally asked during the conversation or that is asked to check one’s root knowledge.

There might be some aspects which I forgot to explain but as soon as I get to know I would try my fullest to update and as you know that this conversation began from widgets and it should go further to with different topics of flutter or as a series and in the next topic we would come with some new fundamental things.

Thanks for reading this article if you find anything that could be improved please let me know, I would love to improve.💙

If this article has helped you a bit and found interesting please clap!👏


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

Feel free to connect with us:
And read more articles from FlutterDevs.com.

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.

Related: Streamlining Payments In Flutter

Need expert help building your Flutter app? Talk to FlutterExperts for architecture, development, and consulting support.

Interactive Viewer In Flutter

0

The Interactivity in Flutter just became 100 times better with the new widget called —Interactive Viewer, released in Flutter version 1.20, It immediately became the one thing everyone fell in love with(yes, including me.)

So, What does the widget do ?

By wrapping up your widgets in Interactive Viewer you can do actions such as drag, drop, zoom etc. with your widgets and not only that but with the introduction of Flutter version 1.20 the drag and drop capabilities have became even more polished.


An example of what this widget is capable of :

zoom and drag just by wrapping the image with one widget

Now, lets talk about how it works:

1. Lets take an image and save it in the assets folder.

2.Now add that image to the pubsepc.yaml file:

assets:
- assets/tiger.jfif

3. after that we can use the image in our app like this

import 'package:flutter/material.dart';

void main() =>runApp(MyApp());

class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
String tiger = "assets/tiger.jfif";
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: SafeArea(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10.0),
child: Center(
child: Image.asset(tiger),
),
),
),
),
);
}
}

4. Now all we need to do is to wrap that image.asset widget with interactiveViewer and we are done :

Tip: use the alt+enter command on android studio, saves a lot of time.

InteractiveViewer(
child: Image.asset(tiger),
),

And now you are done, you can now interact with your image however you Like

Now that we know what the widget does and how to use it, lets explore what it is capable of :

There are certain properties of Ineractive Viewer widget so lets explore them.

Note : before we start exploring some of the properties of this widget it will be better to take a look at the official documentation as well.

InteractiveViewer class
API docs for the InteractiveViewer class from the widgets library, for the Dart programming language.api.flutter.dev

Now, we can jump straight into it.

  1. maxScale

One of the best and most used properties of this widget would be maxScale, it represents how much you can stretch the image.It takes the value of double in it.

Example :

InteractiveViewer(
child: Image.asset(tiger),
maxScale: 5.0,
),

with this you will be able to stretch it 5 times more than what you were able to before, this property helps us to set how much stretch should be allowed on an image.

2. minScale

This property works opposite to maxScale, however it take a double value as well. It represents how much you can squeeze an image.

Example :

InteractiveViewer(
child: Image.asset(tiger),
minScale: 0.1,
),

3. boundaryMargin

Any transformation in the image that results in the viewport being able to view outside of the boundaries will instead be stopped at the boundaries,

This property helps us to keep a certain margin between the corners of the image and the viewport boundaries of our device

Example :

InteractiveViewer(
child: Image.asset(tiger),
boundaryMargin: EdgeInsets.all(5.0),
),

4. onInteractionEnd

A property that takes a ScaleEndDetails variable and lets you execute whatever function you want inside it, you can even print the details like

Example :

Column(
children: [
Expanded(
child: Center(
child: InteractiveViewer(
child: Image.asset(tiger),
boundaryMargin: EdgeInsets.all(5.0),
onInteractionEnd: (ScaleEndDetails endDetails) {
print(endDetails);
print(endDetails.velocity);
setState(() {
velocity = endDetails.velocity.toString();

});
},
),
),
),
Text(velocity)
],
),

you can access the velocity from the endDetails, now i have simply used it to display the velocity by which user is stretching the image.

5. controller

Just like Pageview Listview etc this widget also has a controller, It takes the value of TransformationController to be assigned to this widget

Example :

TransformationController controller = TransformationController();

Now using this you can do many changes with the transformationController but first you have to assign it.

InteractiveViewer(
child: Image.asset(tiger),
transformationController: controller,
boundaryMargin: EdgeInsets.all(5.0),
onInteractionEnd: (ScaleEndDetails endDetails) {
print(endDetails);
print(endDetails.velocity);
setState(() {
velocity = endDetails.velocity.toString();

});
},
),

After assigning it you can do something like reverting the image back to its original position after user is done stretching it, so for that we will use onInteractionEnd with the controller

Before we start, first you need to know that controller can access a special property called “value” which is of type Matrix4

(You might Need to research about matrices before diving straight into using them)

Now we can change the controller’s value inside onInteractionEnd like this

controller.value = Matrix4.identity();

Now what is Matrix4.identity()? Well its basically an identity matrix

Identity Matrix is this :

identity matrix

Now what it does it that it returns the controller to its original value, and that’s what our aim is to return the image to its normal size after user is done transforming it.

TransformationController controller = TransformationController();
String velocity = "VELOCITY";
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: SafeArea(
child: Container(
child: Column(
children: [
Expanded(
child: Center(
child: InteractiveViewer(
child: Image.asset(tiger),
transformationController: controller,
boundaryMargin: EdgeInsets.all(5.0),
onInteractionEnd: (ScaleEndDetails endDetails) {
print(endDetails);
print(endDetails.velocity);
controller.value = Matrix4.identity();
setState(() {
velocity = endDetails.velocity.toString();

});
},
),
),
),
Text(velocity,style: TextStyle(
fontWeight: FontWeight.bold),)
],
),
),
),
),
);
}
auto resizing to default when you let go.

These are just basic and most used properties of Interactive Viewer widget, you can find more of them at the official documentation.

Hope you enjoyed reading through the wall of text and gif’s, let me know in comments if you face any problem. I will try my best to help you out.


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.

Need expert help building your Flutter app? Talk to FlutterExperts for architecture, development, and consulting support.

Date and Time Picker In Flutter

0

In this article, we will explore the Date and Time Picker in a flutter. We will not be using any package in this application. We will use some core functions available in flutter to achieve this. We will implement a demo of the Date and Time Picker in your flutter applications.


Table of Contents :

Date And Time Picker

Code Implementation

Code File

Conclusion


Date And Time Picker

A date and time picker for a flutter, you can choose date/time / date&time in English, Dutch, and any other language you will want, and you can also custom your own picker content.

Demo Module ::

Demo.gif

Code Implementation

Create a new dart file called DateTimePicker.dart inside the lib folder.

In this screen, You will be able to choose the date and time by tapping on them in your Application.

Future<Null> _selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
initialDatePickerMode: DatePickerMode.day,
firstDate: DateTime(2015),
lastDate: DateTime(2101));
if (picked != null)
setState(() {
selectedDate = picked;
_dateController.text = DateFormat.yMd().format(selectedDate);
});
}

Initialize DateTime pickers class.that will save our picked Date.

And in onTap of TextFromField, we call _selectDate function then the show will be shown the picker and save the picked date and time.

InkWell(
onTap: () {
_selectDate(context);
},
child: Container(
width: _width / 1.7,
height: _height / 9,
margin: EdgeInsets.only(top: 30),
alignment: Alignment.center,
decoration: BoxDecoration(color: Colors.grey[200]),
child: TextFormField(
style: TextStyle(fontSize: 40),
textAlign: TextAlign.center,
enabled: false,
keyboardType: TextInputType.text,
controller: _dateController,
onSaved: (String val) {
_setDate = val;
},
decoration: InputDecoration(
disabledBorder:
UnderlineInputBorder(borderSide: BorderSide.none),
contentPadding: EdgeInsets.only(top: 0.0)),
),
),
),

It is just a _selectTime function, as shown down here.

Future<Null> _selectTime(BuildContext context) async {
final TimeOfDay picked = await showTimePicker(
context: context,
initialTime: selectedTime,
);
if (picked != null)
setState(() {
selectedTime = picked;
_hour = selectedTime.hour.toString();
_minute = selectedTime.minute.toString();
_time = _hour + ' : ' + _minute;
_timeController.text = _time;
_timeController.text = formatDate(
DateTime(2019, 08, 1, selectedTime.hour, selectedTime.minute),
[hh, ':', nn, " ", am]).toString();
});}

Initializing TimeOfDay pickers class that will save our picked Time in _selecteTime Function.

On Tapping at TextFormField , We call a _selectTime Function which will show the date & time picker saving the picked time .

InkWell(
onTap: () {
_selectTime(context);
},
child: Container(
margin: EdgeInsets.only(top: 30),
width: _width / 1.7,
height: _height / 9,
alignment: Alignment.center,
decoration: BoxDecoration(color: Colors.grey[200]),
child: TextFormField(
style: TextStyle(fontSize: 40),
textAlign: TextAlign.center,
onSaved: (String val) {
_setTime = val;
},
enabled: false,
keyboardType: TextInputType.text,
controller: _timeController,
decoration: InputDecoration(
disabledBorder:
UnderlineInputBorder(borderSide: BorderSide.none),
// labelText: 'Time',
contentPadding: EdgeInsets.all(5)),
),
),
),

Code File :

import 'package:date_format/date_format.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class DateTimePicker extends StatefulWidget {
@override
_DateTimePickerState createState() => _DateTimePickerState();
}

class _DateTimePickerState extends State<DateTimePicker> {
double _height;
double _width;

String _setTime, _setDate;

String _hour, _minute, _time;

String dateTime;

DateTime selectedDate = DateTime.now();

TimeOfDay selectedTime = TimeOfDay(hour: 00, minute: 00);

TextEditingController _dateController = TextEditingController();
TextEditingController _timeController = TextEditingController();

Future<Null> _selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
initialDatePickerMode: DatePickerMode.day,
firstDate: DateTime(2015),
lastDate: DateTime(2101));
if (picked != null)
setState(() {
selectedDate = picked;
_dateController.text = DateFormat.yMd().format(selectedDate);
});
}

Future<Null> _selectTime(BuildContext context) async {
final TimeOfDay picked = await showTimePicker(
context: context,
initialTime: selectedTime,
);
if (picked != null)
setState(() {
selectedTime = picked;
_hour = selectedTime.hour.toString();
_minute = selectedTime.minute.toString();
_time = _hour + ' : ' + _minute;
_timeController.text = _time;
_timeController.text = formatDate(
DateTime(2019, 08, 1, selectedTime.hour, selectedTime.minute),
[hh, ':', nn, " ", am]).toString();
});
}

@override
void initState() {
_dateController.text = DateFormat.yMd().format(DateTime.now());

_timeController.text = formatDate(
DateTime(2019, 08, 1, DateTime.now().hour, DateTime.now().minute),
[hh, ':', nn, " ", am]).toString();
super.initState();
}

@override
Widget build(BuildContext context) {
_height = MediaQuery.of(context).size.height;
_width = MediaQuery.of(context).size.width;
dateTime = DateFormat.yMd().format(DateTime.now());
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Date time picker'),
),
body: Container(
width: _width,
height: _height,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
children: <Widget>[
Text(
'Choose Date',
style: TextStyle(
fontStyle: FontStyle.italic,
fontWeight: FontWeight.w600,
letterSpacing: 0.5),
),
InkWell(
onTap: () {
_selectDate(context);
},
child: Container(
width: _width / 1.7,
height: _height / 9,
margin: EdgeInsets.only(top: 30),
alignment: Alignment.center,
decoration: BoxDecoration(color: Colors.grey[200]),
child: TextFormField(
style: TextStyle(fontSize: 40),
textAlign: TextAlign.center,
enabled: false,
keyboardType: TextInputType.text,
controller: _dateController,
onSaved: (String val) {
_setDate = val;
},
decoration: InputDecoration(
disabledBorder:
UnderlineInputBorder(borderSide: BorderSide.none),
// labelText: 'Time',
contentPadding: EdgeInsets.only(top: 0.0)),
),
),
),
],
),
Column(
children: <Widget>[
Text(
'Choose Time',
style: TextStyle(
fontStyle: FontStyle.italic,
fontWeight: FontWeight.w600,
letterSpacing: 0.5),
),
InkWell(
onTap: () {
_selectTime(context);
},
child: Container(
margin: EdgeInsets.only(top: 30),
width: _width / 1.7,
height: _height / 9,
alignment: Alignment.center,
decoration: BoxDecoration(color: Colors.grey[200]),
child: TextFormField(
style: TextStyle(fontSize: 40),
textAlign: TextAlign.center,
onSaved: (String val) {
_setTime = val;
},
enabled: false,
keyboardType: TextInputType.text,
controller: _timeController,
decoration: InputDecoration(
disabledBorder:
UnderlineInputBorder(borderSide: BorderSide.none),
// labelText: 'Time',
contentPadding: EdgeInsets.all(5)),
),
),
),
],
),
],
),
),
);
}
}

Conclusion :

In this article, I have explained a date time picker demo, you can modify and experiment according to your own, this little introduction was from the date time picker from our side.

I hope this blog helps will provide you with sufficient information in Trying up the Date Time Picker in your flutter project. So please try it.

❤ ❤ Thanks for reading this article ❤❤


If I got something wrong? Let me know in the comments. I would love to improve.

Clap 👏 If this article helps you.


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.

Related: Socket Communication in Flutter: Building Real-time Apps

Need expert help building your Flutter app? Talk to FlutterExperts for architecture, development, and consulting support.


Custom Shared Preferences In Flutter

0

This article will walk you through the basics of file I/O and in the end, You will be able to build your own storage service just like shared preference using Dart: IO library.

For Complete Project Checkout :

flutter-devs/own-shared-preferences
A new Flutter project. This project is a starting point for a Flutter application. A few resources to get you started…github.com

Our main aim is to dig deep into Flutter file I/O so for that, we are creating our own shared preferences just to learn the basics of file I/O.


Shared preferences in flutter allow the developer to store some sort of state weather it’s related to user data like the day-night theme or some app-level data which we want to persist even after closing the app.

Let’s start by jumping straight into our Database Code for Complete Code along with UI checkout the above git repository.

import 'dart:io';
import 'dart:convert';
import 'package:path_provider/path_provider.dart';

class CoreDb {
//Creating singleton of CoreDb
CoreDb._();
static CoreDb _obj;
static instance() {
if (_obj == null) _obj = CoreDb._();
return _obj;
}

//Getting document path using path provider package
Future<String> get _localPath async {
final directory =
await getApplicationDocumentsDirectory();
return directory.path;
}

//getting instance of file using localPath
Future<File> get _localFile async {
final path = await _localPath;
return File('$path/preference.json');
}

//function to write data in file
void writeData(Map data) async {
File file = await _localFile;
Map<String, dynamic> tempMap;

if (await file.exists()) {
tempMap = json.decode(
file.readAsStringSync());
tempMap.addAll(data);
file.writeAsStringSync(json.encode(
tempMap));
} else {
file.writeAsStringSync(
json.encode(data));
}
}

//Function to get all the data in json format
Future<Map> getData({String key}) async {
File tempFile = await _localFile;
if (await tempFile.exists()) {
return json.decode(tempFile.readAsStringSync());
} else
return null;
}

//To delete data if exist in the file
Future deleteData(
String dataToDelete, Function onDelte, Function ifNotExist) async {
File tempFile = await _localFile;
if (!tempFile.existsSync()) {
ifNotExist();
} else {
Map data = json.decode(tempFile.readAsStringSync());
var result = data.remove(dataToDelete);
if (result == null) {
ifNotExist();
} else {
tempFile.writeAsStringSync(json.encode(data));
onDelte();
}
}
}
}

In the above code we are Interacting with files on our device using dart.io library the above code replicates the same functionality of shared Preferences.

Let’s take a look at each and every function one by one :

  1. localPath() : In localpath() we are accessing document directory using path provider package by calling getApplicationDocumentsDirectory(); method. This function returns a path of type string, we will be using this path for storing our Database file.
  2. localFile(): Now as we got our path from localPath() , We are now creating a file of type JSON using the path we got from localPath() and returning a File as an output return File(‘$path/preference.json’);
  3. writeData(): In this, we are first storing the file reference in a file variable File file = await _localFile; now we can access the same file, Now we create a temporary map and store the JSON file in it by parsing it using json.decode() tempMap = json.decode(file.readAsStringSync()); , After that, we add the new map to the tempMap variable using tempMap.addAll(data); now we right back the updated data by using json.Encode file.writeAsStringSync(json.encode(
     tempMap));
  4. getData(): This function returns a future Map if the file exist this function returns all the data present in the file by calling json.decode(tempFile.readAsStringSync()); .
  5. deleteData(): It takes three-parameter, Last two parameters (onDelete,ifNotExist) is called when the file got successfully deleted or when the file doesn’t exist. The first parameter takes a key of type string and removes that key-value pair if it exists using data.remove(dataToDelete); , This function (data.remove( )) returns null if the file dosent exist and returns the value if it exist .

Conclusion

In this article we learned how to do basic file I/O operations in flutter and alongside we also learned how to parse JSON file using dart: convert library and accessing the device storage using path_provider package. Now go on and create your own file storage system or customize it as per your need ,Sky is the limit 🙃🙃🙃.

Check out the working prototype at:

flutter-devs/own-shared-preferences
A new Flutter project. This project is a starting point for a Flutter application. A few resources to get you started…github.com

Thanks for reading this article.

If you find it interesting Please Clap! and if you found anything wrong please let me know I would appreciate it for your contribution.

From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.

Related: Explore Precache Images In Flutter

Need expert help building your Flutter app? Talk to FlutterExperts for architecture, development, and consulting support.

Flutter 1.20 — What’s New In Flutter

0

Google, the search giant recently rolled out the new stable version of its Extensive Popular Cross-Platform UI Framework Flutter.

Flutter 1.20 & Dart 2.9 have been released simultaneously this time with apparently Substantial Performance Improvements from their contemporary releases . Flutter is now equipped for building apps for iOS, Android, Fuchsia, web & Desktop with new platform support on talks with Ubuntu for Linux apps, Microsoft’s Android Surface Duo, and Windows 10X devices will also be soon available.

Some Prominent advancements are Reduced size & Latency, less janky starting animations, and faster handling of UTF-8 strings, mouse cursor support, new widgets like Interactive viewer making pan, zoom & drag-n-drop easier, range slider & date picker revamped, newly flutter browser variant of dart dev tools, and its embedding in the new VS Code extension keeping all in one window frame for better debugging, Integrating flutter to the existing app made convenient with Pigeon, improved support for Metal on iOS, and new Material widgets.


4 Main Pillar Improvements this release mainly focusses are :

4 main pillar flutter release is focussed on

There is a lot in the release and a lot is yet to come but to sum it up in a Blog

Some of the Key Announcements In Release are ::>

Interactive Viewer : Newly Added Widget

The interactive Viewer widget is Added In the Newly Update providing flutter the Ability to Enable Pan, Resize, Zoom & Drag-n-Drop like Simple Interactions in Flutter Apps.

To Learn How To Embed Your Apps with the Interactive Viewer Widget Checkout the Flutter API documentation :

InteractiveViewer class
API docs for the InteractiveViewer class from the widgets library, for the Dart programming language.api.flutter.dev

Sample Explaining the Capabilities of Interactive Viewer Widget :

Interactive Viewer Sample

A New Similar Kind of update release is the newly added specific target ability to the Drag ’n’ drop making It precise demonstrated in the example below :

New Capabilities have been added to drag-n-drop

Read The Blog Explaining Interactive Viewer By FlutterDevs :

Interactive Viewer In Flutter
The interactivity in Flutter just became 100 times better with the new widget called — Interactive Viewer, release in…medium.com

Mobile Autofill Support

One of the Most Highly Anticipated Release update among the Developer Community is text autofill support in flutter apps. With Flutter 1.20, Flutter has added the basic autofill functionality so that — no further need to re-enter data already gathered by OS.

Autofill Support for Web Apps is also on the Further Updates lined-up

Mobile Autofill Support In Flutter Apps

Slider & Range Slider Update

Slider and RangeSlider have been updated in the newly version keeping in sync with the Material guidelines.

New Discrete Slider
With Value Indicator

Check Out the Medium Article to Know About All New In Sliders :

What’s new with the Slider widget?
Flutter lets you create beautiful, natively compiled applications. The reason Flutter can do this is because Flutter…medium.com

DatePicker & Time Picker Update

DatePicker update comes with support for Date ranges and Close-Packed design.

New DatePicker

TimePicker Design has also come Up with a Change

Updated TimePicker

Typesafe Platform channels via Pigeon

A Command Line Tool Pigeon, at which the messaging protocol is defined in a subset of Dart which then generates messaging code for Android or iOS forming the communication between the two — Flutter & Host Platform safer and easier for plugins and Add-to-App is developed for Platform Interops.

Pigeon example

Pigeon file:

import 'package:pigeon/pigeon.dart';
class SearchRequest {
String query;
}
class SearchReply {
String result;
}
@HostApi()
abstract class Api {
SearchReply search(SearchRequest request);
}

Dart Usage :

import 'generated_pigeon.dart'
void onClick() async {
SearchRequest request = SearchRequest()..query = 'test';
Api api = Api();
SearchReply reply = await api.search(request);
print('reply: ${reply.result}');
}

Though Pigeon is still in the Pre-Release phase, You can Try it out In Your Projects with the Documentation & Sample Project Lending you a Helping Hand.

Documentation :

Writing custom platform-specific code
This guide describes how to write custom platform-specific code. Some platform-specific functionality is available…flutter.dev

Sample Project :

flutter/samples
This application simulates a mock scenario where an existing app with business logic and middleware already exists…github.com

Null Safety In Dart :

Make your apps more stable and performant with Dart’s null safety. Sound null safety is a distinctive feature of Dart that helps you write less error-prone code and get better performance.

Dart is a type-safe language. This means that when you get a variable of some type, the compiler can guarantee that it is of that type. But type safety by itself doesn’t guarantee that the variable is not null.

The null safety feature makes this problem go away:

Try out the Null Safety Enable Dartpad to check the features : —

DartPad
Edit descriptionnullsafety.dartpad.dev

Checkout the dart.dev blog explaining null safety : —

Understanding null safety
Null safety is the largest change we’ve made to Dart since we replaced the original unsound optional type system with a…dart.dev

Import Statement Update

VS Code is updated to enable the functionality of Automatic Updation of Import Statements on file renaming | moving

Import statement updates on moving dart files

Note : Multiple File| Folder Support Is not yet supported

Mouse Cursor Support

Desktop Performance will likely be Improved with the Mouse Cursor Support with refactored mouse hit testing system optimizing Desktop Form Factors.

new mouse cursors over existing widgets

Dart Dev Tools Update

Google has recently added a new VS Code Extension Integrating Dart DevTools enabled by dart.previewEmbeddedDevTools setting.

Preview of Layout Explorer from Dart DevTools embedded into Visual Studio Code

You can also select from the menu which pages to show or to display Devtools in the newly flutter build browser version :

Select DevTools page

Checkout the Flutter Team Blog Explaining the reason they felt the need to build dart DevTools from Scratch In Flutter :

New tools for Flutter developers, built in Flutter
Why we rebuilt Dart DevTools from scratch in Fluttermedium.com

Availing Meta Data For Tool Builders :

Check the following Github Project for Flutter Framework itself. This metadata is used for the Android studio, IntelliJ & VS Code Extensions by the flutter Team and Possibly by tool builders

flutter/tools_metadata
This repo holds generated metadata about the Flutter framework. The metadata is useful for Flutter related tooling and…github.com

Other Significant Changes

:: Google has announced that it is partnering with the Ubuntu Desktop Team at Canonical to bring Flutter apps to Linux.

Google partners with Canonical to bring Flutter apps to Linux
Google has been hard at work creating and expanding Flutter for the past few years. When we last talked about Flutter…www.xda-developers.com

:: Cupertino Icons and Colors are now rendered, Improved Outlines, performance fix for tree-shake-icons, Mouse Cursor Support, Improved Debug Discoverability in VS Code.

  • Unsupported Platforms Update: The flutter project will show enable option for Unsupported platforms.
Improved handling of Unsupported platforms

:: New Pubspec Format — New Pubspec format is required for further Updating | New Plugin Development as the old formats Inability Specifying platform Support for Plugins.

Check Out The NewPubspec.yamlformat required for publishing new/update Plugins :

Developing packages & plugins
The plugin API has been updated and now supports federated plugins that enable separation of different platform…flutter.dev

Note: All Existing Plugins with the Old Pubspec format will Continue to work in the Existing future Without any Hindrance.

Closing Thoughts

Flutter 1.20 — Apparently Described as the biggest release in the Flutter history. The update release has created an igniting spark among the mobile developer’s Community by focussing well on varied Important Aspects.

Though Each New Release Certainly Brings with In Increased usage and momentum Which can be easily seen that the number of Flutter apps in play store reached from an astonishingly 50k to 90k in the span of mere 3 months. Also, Flutter being well supported by the Dart which has now moved up further to the #12 in the top 50 languages: reported by IEEE

What makes it more special for us is that Our Country, India now being the #1 region for Flutter developers, having doubled in the last six months

Much More Yet To Come: Enhanced Null Support, a new version of the Ads, Maps, and WebView plugins & Tooling Updates.

Check Out The Original Post By Flutter To know more about the Update.

References For the Blog :

Flutter – Beautiful native apps in record time
Flutter is Google’s UI toolkit for crafting beautiful, natively compiled applications for mobile, web, and desktop from…flutter.dev

Announcing Flutter 1.20
Performance improvements, mobile autofill, a new widget and more!medium.com


🌸🌼🌸 Thank You For Reading 🌸🌼🌸🌼


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

Feel free to connect with us:
And read more articles from FlutterDevs.com

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences.

Related: SMS Using Twilio In Flutter

Related: Using SharedPreferences in Flutter

Need expert help building your Flutter app? Talk to FlutterExperts for architecture, development, and consulting support.

www.flutterdevs.com

Hooks In Flutter

0

Welcome to one of the best ways of managing UI logic, forget all about stateful widgets and the amount of unreadability as you pile hundreds of functions into initState() or call setState() hundred times.
So, that brings us to a question of what hooks are exactly?

Hooks came from React Native, if you want to learn more about them

https://reactjs.org/docs/hooks-intro.html

With them in react you could use state features without writing a class, So what do they do in flutter then?


well, their main use is for readability and clear the clutter in your state classes, they use something called HOOKWIDGET, now with stateful widgets, you can only have one state but with Hookwidget you can have multiple hooks attached to one HookWidget each containing its own logic.

Hooks are kept inside a List and are managed on their own so you don’t need to initialize them or dispose of them(well not the prebuilt ones anyway)

There are prebuilt Hooks and Custom hooks that we can use.To get a better understanding of Hooks lets just jump into code

Without using a HookWidget :

import 'package:flutter/animation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

void main()=>runApp(MaterialApp(
title: "Hooks",
home: Home(),
debugShowCheckedModeBanner: false,
));

class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> with SingleTickerProviderStateMixin{
AnimationController animationController;
Animation<double> animation;


@override
void initState() {
super.initState();
animationController = AnimationController(vsync: this,duration: Duration(milliseconds: 1000),value: 1)..addListener(() {
if(animationController.status == AnimationStatus.completed) {
animationController.repeat();
}
setState(() {

});
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.blueGrey,
child: GestureDetector(
child: FadeTransition(opacity: animationController,child: Center(child: FlutterLogo(size: 300,))),
onTap: animationController.forward,
onDoubleTap: animationController.reverse,
),
),
);
}

@override
void dispose() {
super.dispose();
animationController.dispose();
}
}

we are simply trying to Fade the flutter logo when the user taps on Screen, just create an animation controller and an Animation and call _animationController.forward(), to make it run.

Now the equivalent of this in Hooks would be

import 'package:flutter/animation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

void main()=>runApp(MaterialApp(
title: "Hooks",
home: Home(),
debugShowCheckedModeBanner: false,
));



class Home extends HookWidget {
@override
Widget build(BuildContext context) {
final hookAnimation = useAnimationController(duration: kThemeAnimationDuration, initialValue: 1);

return Scaffold(
body: GestureDetector(
onTap: () {
hookAnimation.forward();
},
onDoubleTap: () {
hookAnimation.reverse();
},
child: Container(
color: Colors.blueGrey,
child: Center(child: FadeTransition(opacity: hookAnimation,child: ScaleTransition(scale: hookAnimation,child: FlutterLogo(colors: Colors.blue,size: 500,)))),

),
),
);
}
}

see the lack of initState(), or even the dispose()?

So why is it that we need to declare them in stateful widget yet we can freely use useAnimationController() in the HookWidget?

Well, the answer to that question is simple, in HookWidget all the different hooks we create like the useAnimationController they are managed by Hook that is to say that their intialization and dispose is taken care of and we don’t need to get our hands dirty by writing them on our own:

Suppose if I had to create 2 TextEditingControllers in this project as well I would’ve had to dispose them and then the dispose method would’ve been cluttered, now imagine this for a project on a huge scale where multiple people are working on it, imagine you had to put so many functions in the initState or call setState so many times that it takes a while just to read and understand the code and then make changes to a particular part of the program, there is a chance you may even break something trying to fix something else which would consume even more time.

So that is why Hooks are the perfect solution provided to us so that we do not run into this particular problem. Another benefit of using hooks is re-usability, after creating your custom hook you can reuse it as much as you would like.

NOTE: Always create the hooks in build method.

CREATING CUSTOM HOOKS

let’s say you want the animation you just created to show up when you scroll the page?

Simple right you will just create a scroll controller and in initState just define it to do that, but what if you had to do the same thing on like 5 or 6 different screens? nobody would write the same stuff 5–6 times just for it to work, that’s where hook comes in and saves your day. Lemme show you how :

How would you do that in normal Stateful Widget?

class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> with SingleTickerProviderStateMixin{
AnimationController animationController;
Animation<double> animation;
ScrollController scroller;


@override
void initState() {
super.initState();

animationController = AnimationController(vsync: this,duration: Duration(milliseconds: 1000),value: 1);
scroller = ScrollController()..addListener(
() {
if(scroller.position.userScrollDirection ==ScrollDirection.forward) {
animationController.forward();
}
else if(scroller.position.userScrollDirection ==ScrollDirection.reverse) {
animationController.reverse();
}
else {
print("not scrolloing");
}
}
);
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.blueGrey,
child: ListView(
controller: scroller,
children: List.generate(20, (index) {
return Container(
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 10
)
),
child: GestureDetector(
child: FadeTransition(opacity: animationController,child: Center(child: FlutterLogo(size: 300,))),
onTap: animationController.forward,
onDoubleTap: animationController.reverse,
),
);
}),
)
),
);
}

@override
void dispose() {
super.dispose();
animationController.dispose();
scroller.dispose();
}


}

So, I have made a simple example of when you scroll the animation plays, and when you scroll in reverse direction the animation also plays in reverse, its simple code but if you have no practice with ScrollController then you might wanna check out :

ScrollController class
Controls a scrollable widget. Scroll controllers are typically stored as member variables in State objects and are…api.flutter.dev

Alright now that you are familiar with ScrollController class we can focus on how to get this done with the help of a CustomHook

While it may sound difficult thing to do its really not,

so i have created another file called customScroll where i have created a class called HookScroll which extends Hook<ScrollController>, now just like in a normal stateful class you need to create an createState().

TIP : Just create a normal stateful class in your project then modify it with the code i m about to paste, will save a lot of time

Now create a _HookScrollState which will HookState which will have 2 generics one of ScrollController and the other of the class it will be the state of HookScroll , So it will go like this

class _HookScrollerState extends HookState<ScrollController,HookScroller> {

Now we will create a normal ScrollController instance, and in initState for a hook called the initHook we will define it

@override
void initHook() {
// TODO: implement initHook
super.initHook();
scroller = ScrollController()..addListener((){
scrollAnimation(hook.controller, scroller);
});
}

the scrollAnimation is a function defined by me but you can just create it inside scrollController’s addListener i just like to keep my functions seperate, here is the code for it

void scrollAnimation(AnimationController controler, ScrollController scrollController) {
if(scrollController.position.userScrollDirection == ScrollDirection.forward) {
controler.forward();
}
else if(scrollController.position.userScrollDirection == ScrollDirection.reverse){
controler.reverse();
}
else {
print("not scrolling rn");
}
}

now after making an initHook just like an initState we are going to need a dispose for the scroll controller

@override
void dispose() {
// TODO: implement dispose
super.dispose();
scroller.dispose();
}

Alright, now we can wire it up so that HookScroll takes an animation controller value which we can access by hook.controller

class HookScroller extends Hook<ScrollController> {
AnimationController controller;
HookScroller(this.controller);
  @override
_HookScrollerState createState() => _HookScrollerState();
}

Now after all that we need a build method so that it can all work together so for that just paste the below code

@override
ScrollController build(BuildContext context) {
return scroller;
}

Body is of type ScrollerController meaning it returns the scroller that we created so that

in the end it would look like this

class HookScroller extends Hook<ScrollController> {
AnimationController controller;
HookScroller(this.controller);
@override
_HookScrollerState createState() => _HookScrollerState();
}

class _HookScrollerState extends HookState<ScrollController,HookScroller> {
ScrollController scroller;

void scrollAnimation(AnimationController controler, ScrollController scrollController) {
if(scrollController.position.userScrollDirection == ScrollDirection.forward) {
controler.forward();
}
else if(scrollController.position.userScrollDirection == ScrollDirection.reverse){
controler.reverse();
}
else {
print("not scrolling rn");
}
}

@override
void initHook() {
// TODO: implement initHook
super.initHook();
scroller = ScrollController()..addListener((){
scrollAnimation(hook.controller, scroller);
});
}

@override
ScrollController build(BuildContext context) {
return scroller;
}

@override
void dispose() {
// TODO: implement dispose
super.dispose();
scroller.dispose();
}
}

With this we can make a scroll work, just one little problem tho if you try to make an instance of it, It will give you an error, why is that?

Well when you call a HookWidget inside a class that extends Hook,it does that by calling Hook.use, so to fix this you can click on useAnimationController() method we created while holding ctrl button on the keyboard to visit this function, as you can see how that function returns a Hook.use with _AnimationControllerHook, so we have do perform the same with our custom Hook.

To do this outside of the classes of our HookScroller and _HookScrollState create a method that will return a ScrollController which will need the value of an animation controller called controller

ScrollController scrollController(AnimationController controller) {
return Hook.use(HookScroller(controller));
}

After creating this the final would customScroll file would look like this :

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_hooks/flutter_hooks.dart';


class HookScroller extends Hook<ScrollController> {
AnimationController controller;
HookScroller(this.controller);
@override
_HookScrollerState createState() => _HookScrollerState();
}

class _HookScrollerState extends HookState<ScrollController,HookScroller> {
ScrollController scroller;

void scrollAnimation(AnimationController controler, ScrollController scrollController) {
if(scrollController.position.userScrollDirection == ScrollDirection.forward) {
controler.forward();
}
else if(scrollController.position.userScrollDirection == ScrollDirection.reverse){
controler.reverse();
}
else {
print("not scrolling rn");
}
}

@override
void initHook() {
// TODO: implement initHook
super.initHook();
scroller = ScrollController()..addListener((){
scrollAnimation(hook.controller, scroller);
});
}

@override
ScrollController build(BuildContext context) {
return scroller;
}

@override
void dispose() {
// TODO: implement dispose
super.dispose();
scroller.dispose();
}
}

ScrollController scrollController(AnimationController controller) {
return Hook.use(HookScroller(controller));
}

Finally, we can wire it all up together by calling the method we just created in our Home class

class Home extends HookWidget {
@override
Widget build(BuildContext context) {
final hookAnimation = useAnimationController(duration: Duration(milliseconds: 500), initialValue: 0);
final hookScroll = scrollController(hookAnimation);

return Scaffold(
body: GestureDetector(
onTap: () {
hookAnimation.reverse();
},
onDoubleTap: () {
hookAnimation.forward();
},
child: Container(
color: Colors.blueGrey,
child: ListView(
controller: hookScroll,
children: List.generate(20, (index) {
return Container(margin: EdgeInsets.all(20),decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 2,
style: BorderStyle.solid
)
),child: Center(child: FadeTransition(opacity: hookAnimation,child: ScaleTransition(scale: hookAnimation,child: FlutterLogo(colors: Colors.blue,size: 500,)))));
})
)

),
),
);
}

}

See the highlighted above and do the same in your code, or you can copy-paste it, I leave that decision up to you
With this, we are done. now we can have it play our animation every time we scroll

If you wanna say that this is too much boilerplate code compared to what we had in StatefulWidget…. well, I agree, if I just have to make it for one screen alone then I won’t make a hook for it and just work with a stateful widget, but if I have to use that animation in like 3–4 screens nothing would be better than a CustomHook.

If you are facing any problem implementing Hook, contact me i will try to help to the best of my ability

You can find the full code and more amazing stuff at :

flutter-devs/flutter_hooks_demo
Contribute to flutter-devs/flutter_hooks_demo development by creating an account on GitHub.github.com


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

Feel free to connect with us:
And read more articles from FlutterDevs.com

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences.

Related: SMS Using Twilio In Flutter

Related: Using SharedPreferences in Flutter

Need expert help building your Flutter app? Talk to FlutterExperts for architecture, development, and consulting support.

www.flutterdevs.com

How to handle authentication errors in Flutter 2026

0

Introduction

In this blog, we shall discuss about handing authentication exception. When the user signs in or signup he might get some error but if we do not handle those errors the user will not be able to know about the authentication failure. So it is very important to handle those errors and display a message or alert so that the user can change his credentials as per the requirement of the error.


Table of contents:

Validating TextField

Handle platform exception.

Handle Firebase Auth exceptions

Complete auth module


Validating TextField

Email TextField

TextFormField(
key: ValueKey('email'),
autocorrect: false,
textCapitalization: TextCapitalization.none,
enableSuggestions: false,
validator: (value) {
if (value.isEmpty || !value.contains('@')) {
return 'Please enter a valid email address.';
}
return null;
},
keyboardType: TextInputType.emailAddress,
)

: TextFormField provides us validator property to show an error if the email is empty or it does not contain @. You can add as many error messages you want using nested if-else.

Password TextField

TextFormField(
key: ValueKey('password'),
validator: (value) {
if (value.isEmpty || value.length < 7) {
return 'Password must be at least 7 characters long.';
}
return null;
},
obscureText: hidePassword,

)

Handle Platform exception

This handle the error of different platforms such as android and ios

try {
if (isLogin) {
userCredential = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
} else if (password == confirmPassword) {
userCredential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
} else {}
} on PlatformException catch (err) {
authProblems errorType;
if (Platform.isAndroid) {
switch (e.message) {
case 'There is no user record corresponding to this identifier. The user may have been deleted.':
errorType = authProblems.UserNotFound;
break;
case 'The password is invalid or the user does not have a password.':
errorType = authProblems.PasswordNotValid;
break;
case 'A network error (such as timeout, interrupted connection or unreachable host) has occurred.':
errorType = authProblems.NetworkError;
break;
default:
print('Case ${e.message} is not yet implemented');
}
} else if (Platform.isIOS) {
switch (e.code) {
case 'Error 17011':
errorType = authProblems.UserNotFound;
break;
case 'Error 17009':
errorType = authProblems.PasswordNotValid;
break;
case 'Error 17020':
errorType = authProblems.NetworkError;
break;
// ...
default:
print('Case ${e.message} is not yet implemented');
}
}
Scaffold.of(ctx).showSnackBar(
SnackBar(
content: Text($errorType),
backgroundColor: Theme.of(ctx).errorColor,
),
);
}

Handling both platform error using a single code

var errorMessage;
final _auth = FirebaseAuth.instance;

try {
if (isLogin) {
userCredential = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
} else if (password == confirmPassword) {
userCredential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
}

} on PlatformException catch (err) {
var message = 'An error occurred, please check your credentials!';

if (err.message != null) {
message = err.message;
setState(() {
errorMessage = message;
});
print(message);
}
Scaffold.of(ctx).showSnackBar(
SnackBar(
content: Text(message),
backgroundColor: Theme.of(ctx).errorColor,
),
);
}

Here we are directly displaying the error message using a snack bar. If the error message is null then ‘An error occurred, please check your credentials!’ message will be displayed. If an error message is not null then message = err.message; .

Handle Firebase Auth exceptions

catch (error) {
print(error);
setState(() {
errorMessage = error.toString();
});
Scaffold.of(ctx).showSnackBar(
SnackBar(
content: Text(errorMessage),
backgroundColor: Colors.red,
),
);
}

While logging in user can get the following error :

  • [firebase_auth/wrong-password] The password is invalid or the user does not have a password.
  • [firebase_auth/invalid-email] The email address is badly formatted.
  • [firebase_auth/user-not-found] There is no user record corresponding to this identifier. The user may have been deleted.

While Signing up user can get the following error:

  • [firebase_auth/email-already-in-use] The email address is already in use by another account.
  • [firebase_auth/invalid-email] The email address is badly formatted.
  • [firebase_auth/weak-password] Password should be at least 6 characters.
Types of error

Complete auth module (Ready to use)

Complete Dart Code File for Auth Form :

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:laundary_application/widgets/userImagePicker.dart';

class AuthForm extends StatefulWidget {
AuthForm(
this.submitFn,
this.isLoading,
);

final bool isLoading;
final void Function(
String email,
String password,
String confirmPassword,
String userName,
File image,
bool isLogin,
BuildContext ctx,
) submitFn;

@override
_AuthFormState createState() => _AuthFormState();
}

class _AuthFormState extends State<AuthForm> {
final _formKey = GlobalKey<FormState>();
var _isLogin = true;
var _userEmail = '';
var _userName = '';
var _userPassword = '';
var _confirmPassword = '';
File _userImageFile;
bool hidePassword = true;

void _pickedImage(File image) {
_userImageFile = image;
}

void _trySubmit() {
final isValid = _formKey.currentState.validate();
FocusScope.of(context).unfocus();

if (_userImageFile == null && !_isLogin) {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('Please pick an image.'),
backgroundColor: Theme.of(context).errorColor,
),
);
return;
}

if (isValid) {
_formKey.currentState.save();
widget.submitFn(
_userEmail.trim(),
_userPassword.trim(),
_confirmPassword.trim(),
_userName.trim(),
_userImageFile,
_isLogin,
context,
);
}
}

@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return Center(
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
!_isLogin
? SizedBox(
height: 0,
)
: Image.asset(
"assets/appIcon.png",
height: height * 0.2,
),
if (!_isLogin) UserImagePicker(_pickedImage, widget.isLoading),
Container(
width: width,
height: 50,
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey.withOpacity(0.5),
width: 1,
),
borderRadius: BorderRadius.circular(5),
),
child: TextFormField(
key: ValueKey('email'),
autocorrect: false,
textCapitalization: TextCapitalization.none,
enableSuggestions: false,
validator: (value) {
if (value.isEmpty || !value.contains('@')) {
return 'Please enter a valid email address.';
}
return null;
},
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'Email address',
prefixIcon: Icon(Entypo.mail),
border: InputBorder.none),
onSaved: (value) {
_userEmail = value;
},
),
),
SizedBox(height: 12),
if (!_isLogin)
Container(
width: width,
height: 50,
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey.withOpacity(0.5),
width: 1,
),
borderRadius: BorderRadius.circular(5),
),
child: TextFormField(
key: ValueKey('username'),
autocorrect: true,
textCapitalization: TextCapitalization.words,
enableSuggestions: false,
validator: (value) {
if (value.isEmpty || value.length < 4) {
return 'Please enter at least 4 characters';
}
return null;
},
decoration: InputDecoration(
hintText: 'Username',
prefixIcon: Icon(Icons.edit),
border: InputBorder.none,
),
onSaved: (value) {
_userName = value;
},
),
),
SizedBox(height: 12),
Container(
width: width,
height: 50,
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey.withOpacity(0.5),
width: 1,
),
borderRadius: BorderRadius.circular(5),
),
child: TextFormField(
key: ValueKey('password'),
validator: (value) {
if (value.isEmpty || value.length < 7) {
return 'Password must be at least 7 characters long.';
}
return null;
},
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(
hidePassword ? Entypo.eye_with_line : Entypo.eye),
onPressed: () {
setState(() {
hidePassword = !hidePassword;
});
},
),
hintText: 'Password',
border: InputBorder.none,
prefixIcon: Icon(
Icons.vpn_key,
)),
obscureText: hidePassword,
onSaved: (value) {
_userPassword = value;
},
),
),
SizedBox(height: 12),
if (!_isLogin)
Container(
width: width,
height: 50,
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey.withOpacity(0.5),
width: 1,
),
borderRadius: BorderRadius.circular(5),
),
child: TextFormField(
key: ValueKey('password'),
validator: (value) {
if (value.isEmpty || value.length < 7) {
return 'Password must be at least 7 characters long.';
}
return null;
},
decoration: InputDecoration(
hintText: 'Confirm Password',
border: InputBorder.none,
prefixIcon: Icon(
Icons.vpn_key,
)),
obscureText: hidePassword,
onSaved: (value) {
_confirmPassword = value;
},
),
),
SizedBox(height: 12),
widget.isLoading
? CircularProgressIndicator()
: InkWell(
onTap: _trySubmit,
child: Container(
height: 50,
decoration: BoxDecoration(
color: Colors.pinkAccent.withOpacity(0.8),
borderRadius: BorderRadius.circular(5),
),
width: width,
child: Center(
child: Text(
_isLogin ? 'Login' : 'Sign Up',
style: GoogleFonts.lato(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w900,
),
)),
),
),
if (!widget.isLoading)
FlatButton(
child: RichText(
text: TextSpan(children: [
TextSpan(
text: _isLogin
? "Don't have an account? "
: "Already have an account?",
style: GoogleFonts.lato(
color: Colors.black54,
)),
TextSpan(
text: _isLogin ? "Sign Up" : "Log In",
style: GoogleFonts.lato(
color: Colors.red,
fontWeight: FontWeight.w900,
)),
]),
),
onPressed: () {
setState(() {
_isLogin = !_isLogin;
});
},
),
Image.asset(
"assets/demo1.png",
height: height * 0.26,
),
],
),
),
),
),
);
}
}

Let us Have a look at the authentication dart file :

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/services.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:laundary_application/widgets/authForm.dart';

class AuthScreen extends StatefulWidget {
@override
_AuthScreenState createState() => _AuthScreenState();
}

class _AuthScreenState extends State<AuthScreen> {
final _auth = FirebaseAuth.instance;
var _isLoading = false;
var errorMessage;

void _submitAuthForm(
String email,
String password,
String confirmPassword,
String username,
File image,
bool isLogin,
BuildContext ctx,
) async {
UserCredential userCredential;

try {
setState(() {
_isLoading = true;
});
if (isLogin) {
userCredential = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
} else if (password == confirmPassword) {
userCredential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);

final ref = FirebaseStorage.instance
.ref()
.child('user_image')
.child(userCredential.user.uid + '.jpg');

await ref.putFile(image).onComplete;

final url = await ref.getDownloadURL();

await FirebaseFirestore.instance
.collection('users')
.doc(userCredential.user.uid)
.set({
'username': username,
'email': email,
'image_url': url,
});
} else {
setState(() {
_isLoading = false;
errorMessage = "password does not match";
Scaffold.of(ctx).showSnackBar(
SnackBar(
content: Text(errorMessage),
backgroundColor: Colors.red,
),
);
});
}
} on PlatformException catch (err) {
var message = 'An error occurred, please check your credentials!';

if (err.message != null) {
message = err.message;
setState(() {
errorMessage = message;
});
print(message);
}
Scaffold.of(ctx).showSnackBar(
SnackBar(
content: Text(message),
backgroundColor: Theme.of(ctx).errorColor,
),
);
setState(() {
_isLoading = false;
});
} catch (error) {
print(error);
setState(() {
errorMessage = error.toString();
});
Scaffold.of(ctx).showSnackBar(
SnackBar(
content: Text(errorMessage),
backgroundColor: Colors.red,
),
);
setState(() {
_isLoading = false;
});
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: AuthForm(
_submitAuthForm,
_isLoading,
),
),
);
}
}

If you find anything that could be improved please let me know, I would love to improve.💙

If this article has helped you a bit and found interesting please clap!👏


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

Feel free to connect with us:
And read more articles from FlutterDevs.com

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.

Need expert help building your Flutter app? Talk to FlutterExperts for architecture, development, and consulting support.