Before getting started ๐
Goals, requirements, initial setup, and overview:
Link
This post was written for Flutter 3.24.
With the basic development environment ready, let's build a login page.
It is a core part of the app and the user's first step toward using it.
We will use
FlutterSecureStorage
and
Get
to store login information and choose which page to show based on login state.
The following is the file tree inside my lib folder for this post.
Creating the files in advance makes the process easier.
๐ฆ lib
โฃ ๐ model // ๋ฐ์ดํฐ ๋ณด๊ดํ๋ ๋ชจ๋ธ ํด๋(์ด๋ฒ ํฌ์คํ
์์๋ ์ฌ์ฉํ์ง ์์)
โฃ ๐ view // ํ๋ฉด์ ๊ตฌ์ฑํ๋ ๋ทฐ ํด๋
โ โฃ ๐ login_page.dart
โ โ ๐ main_page.dart
โฃ ๐ viewModel // ๋ฐ์ดํฐ์ ํ๋ฉด์ ์๋ viewModel ํด๋
โ โ ๐ auth_service.dart
โ ๐ main.dart
1. Creating the AuthService class ๐
Create AuthService to handle authentication-related work.
Implement methods for login, logout, and checking login state.
Use FlutterSecureStorage to store and inspect that state.
lib/viewModel/auth_service.dart import 'package:flutter_secure_storage/flutter_secure_storage.dart' ;
class AuthService {
// FlutterSecureStorage ์ธ์คํด์ค ์์ฑ (๋ณด์ ๋ฐ์ดํฐ ์ ์ฅ์ฉ)
final _storage = const FlutterSecureStorage ();
// ๋ก๊ทธ์ธ ์ํ ์ ์ฅ (isLoggedIn = true ๋๋ false)
Future < void > saveLoginState ( bool isLoggedIn) async {
await _storage. write (key : 'isLoggedIn' , value : isLoggedIn. toString ());
}
// ๋ก๊ทธ์ธ ์ํ ๋ถ๋ฌ์ค๊ธฐ (์ ์ฅ๋ ๊ฐ์ด 'true'์ธ์ง ํ์ธ)
Future < bool > getLoginState () async {
final value = await _storage. read (key : 'isLoggedIn' );
return value == 'true' ;
}
// ๋ก๊ทธ์์ ์ฒ๋ฆฌ (์ ์ฅ๋ ๋ก๊ทธ์ธ ์ํ ์ญ์ )
Future < void > logout () async {
await _storage. delete (key : 'isLoggedIn' );
}
}
2. Creating the LoginPage class ๐
Create LoginPage to build the login screen.
When the login button is pressed, call AuthService's saveLoginState method to save the login state.
lib/view/login_page.dart import 'package:flutter/material.dart' ;
import 'package:get/get.dart' ;
import 'package:navigationbar_example/viewModel/auth_service.dart' ;
import 'package:navigationbar_example/view/main_page.dart' ;
class LoginPage extends StatelessWidget {
final AuthService _authService = AuthService (); // AuthService ์ธ์คํด์ค ์์ฑ
@override
Widget build ( BuildContext context) {
return Scaffold (
appBar : AppBar (title : const Text ( 'Login' )), // ๋ก๊ทธ์ธ ํ๋ฉด ์ ๋ชฉ
body : Center (
child : ElevatedButton (
onPressed : () async {
// ๋ก๊ทธ์ธ ์ฑ๊ณต ์ ์ํ๋ฅผ ์ ์ฅ (true๋ก ์ค์ )
await _authService. saveLoginState ( true );
// ๋ก๊ทธ์ธ ํ ๋ฉ์ธ ํ์ด์ง๋ก ์ด๋
Get . offAll (() => MainPage ());
},
child : const Text ( 'Login' ), // ๋ก๊ทธ์ธ ๋ฒํผ ํ
์คํธ
),
),
);
}
}
3. Creating the MainPage class ๐
Create MainPage to build the main screen.
When the logout button is pressed, call AuthService's logout method to remove the saved login state.
lib/view/main_page.dart import 'package:flutter/material.dart' ;
import 'package:get/get.dart' ;
import 'package:navigationbar_example/view/login_page.dart' ;
import 'package:navigationbar_example/viewModel/auth_service.dart' ;
class MainPage extends StatelessWidget {
final AuthService _authService = AuthService (); // AuthService ์ธ์คํด์ค ์์ฑ
@override
Widget build ( BuildContext context) {
return Scaffold (
appBar : AppBar (
title : const Text ( 'Main Page' ), // ๋ฉ์ธ ํ๋ฉด ์ ๋ชฉ
actions : [
IconButton (
onPressed : () async {
// ๋ก๊ทธ์์ ์ ์ํ ์ญ์
await _authService. logout ();
// ๋ก๊ทธ์์ ํ ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์ด๋
Get . offAll (() => LoginPage ());
},
icon : const Icon ( Icons .logout), // ๋ก๊ทธ์์ ๋ฒํผ ์์ด์ฝ
),
],
),
body : const Center (
child : Text ( 'Welcome to Main Page!' ), // ๋ฉ์ธ ํ๋ฉด ํ์ ๋ฉ์์ง
),
);
}
}
4. Updating main.dart ๐
lib/main.dart import 'package:flutter/material.dart' ;
import 'package:get/get.dart' ;
import 'package:navigationbar_example/view/login_page.dart' ;
import 'package:navigationbar_example/view/main_page.dart' ;
import 'package:navigationbar_example/viewModel/auth_service.dart' ;
void main () {
runApp ( MyApp ());
}
class MyApp extends StatelessWidget {
final AuthService _authService = AuthService ();
MyApp ({ super .key});
@override
Widget build ( BuildContext context) {
return GetMaterialApp ( // GetMaterialApp์ผ๋ก ๋ณ๊ฒฝํ์ฌ GetX ์ฌ์ฉ
debugShowCheckedModeBanner : false ,
home : FutureBuilder < bool >(
future : _authService. getLoginState (), // ๋ก๊ทธ์ธ ์ํ ํ์ธ ํจ์ ํธ์ถ (๋น๋๊ธฐ ์ฒ๋ฆฌ)
builder : (context, snapshot) {
if (snapshot.connectionState == ConnectionState .waiting) {
// ๋ก๊ทธ์ธ ์ํ ํ์ธ ์ค์ผ ๋ ๋ก๋ฉ ํ๋ฉด ํ์
return const Center (child : CircularProgressIndicator ());
}
if (snapshot.data == true ) {
// ๋ก๊ทธ์ธ ์ํ๊ฐ true์ผ ๋ MainPage๋ก ์ด๋
return MainPage ();
} else {
// ๋ก๊ทธ์ธ ์ํ๊ฐ false์ผ ๋ LoginPage๋ก ์ด๋
return LoginPage ();
}
},
),
);
}
}
5. Checking the result ๐
The login page appears when the app starts.
Press Login to move to the main page, and press Logout to return to the login page.
We have learned how to store login state with FlutterSecureStorage and implement navigation using Get.
In the next post, we will configure the main page with a bottom navigation bar after login.
How can you show a confirmation dialog when the user logs out?
Use the GetX package's Get.defaultDialog() method.
Use the AlertDialogโ widget.