super.initState()
부모 요소의 코드를 그대로 사용
splashScreen 공부
스플래시 스크린에 띄우는 사진
그래서 initalization에서 내가 필요한 로직을 작성
여기에서 로그인로직을 짜고 완료가 되면 다음으로 넘어간다.
initState에는 await를 걸 수 없다.
만약 await를 걸고 싶으면 initState에서 상속받아서 initialization을 실행
아래 initialization에서 await를 걸어서 처리
만약 await를 걸지 못하는 상황이 오면 .then을 사용해도 된다.
myInit에서 필요한 코드를 작성
firebase로 소켓통신으로 푸시알림 같은것이 가능하다.
푸시 알림을 위한 소켓 통신연결을 여기서 한다.
무거운 데이터를 다운 받기도 한다.
SplashPage를 처음 만들어 진다. 여기에서 autoLogin호출
초기화 되는 함수들을 ref.read(sessionProvider).함수 로 필요한 것들 작성
대칭키는 클라이언트 측에서 검증이 안된다. HMAC은 대칭키 → 서버에서 검증해야됨
하지만 RSA같은 비대칭키는 클라이언트에서 직접 검증이 가능하다.
토큰 유효성 검사 예외처리들
토큰만료, 인코딩,
secureStorage로 에 저장된 토큰을 꺼내온다.
통신 성공하면 부모의 SessionUser 정보를 업데이트 해주고 목록페이지로 이동
토큰 로그아웃 로직
Delete는 IO처리이므로 시간이 걸리는 작업
따라서 동기적 처리가 필요한 친구들은 같은 함수내로 묶어서 Future걸고 async걸고 await걸면 delete가 완료된 후에 아래 코드로 이동한다.
import 'package:flutter/material.dart';
import 'package:flutter_blog/ui/pages/auth/login_page/login_page.dart';
class SplashPage extends StatefulWidget {
const SplashPage({super.key});
@override
State<SplashPage> createState() => _SplashPageState();
}
class _SplashPageState extends State<SplashPage> {
@override
void initState() {
super.initState();
Future.delayed(Duration(seconds: 5), () {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => LoginPage()));
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Image.asset(
'assets/splash.gif',
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
),
),
);
}
}
JavaScript
복사
import 'package:flutter/material.dart';
import 'package:flutter_blog/_core/constants/http.dart';
import 'package:flutter_blog/ui/pages/auth/login_page/login_page.dart';
class SplashPage extends StatefulWidget {
const SplashPage({super.key});
@override
State<SplashPage> createState() => _SplashPageState();
}
class _SplashPageState extends State<SplashPage> {
@override
void initState() {
super.initState();
dio.get("/init/download").then((value) => Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => LoginPage())));
// Future.delayed(Duration(seconds: 5), () {
// Navigator.pushReplacement(
// context, MaterialPageRoute(builder: (context) => LoginPage()));
// });
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Image.asset(
'assets/splash.gif',
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
),
),
);
}
}
JavaScript
복사
import 'package:flutter/material.dart';
import 'package:flutter_blog/_core/constants/http.dart';
import 'package:flutter_blog/ui/pages/auth/login_page/login_page.dart';
class SplashPage extends StatefulWidget {
const SplashPage({super.key});
@override
State<SplashPage> createState() => _SplashPageState();
}
class _SplashPageState extends State<SplashPage> {
@override
void initState() {
super.initState();
myInit();
// dio.get("/init/download").then((value) => Navigator.pushReplacement(
// context, MaterialPageRoute(builder: (context) => LoginPage())));
// Future.delayed(Duration(seconds: 5), () {
// Navigator.pushReplacement(
// context, MaterialPageRoute(builder: (context) => LoginPage()));
// });
}
void myInit() async {
await dio.get("/init/download");
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => LoginPage()));
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Image.asset(
'assets/splash.gif',
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
),
),
);
}
}
JavaScript
복사
import 'package:flutter/material.dart';
import 'package:flutter_blog/_core/constants/http.dart';
import 'package:flutter_blog/ui/pages/auth/login_page/login_page.dart';
class SplashTestPage extends StatefulWidget {
const SplashTestPage({super.key});
@override
State<SplashTestPage> createState() => _SplashPageState();
}
class _SplashTestPageState extends State<SplashTestPage> {
@override
void initState() {
super.initState();
myInit();
// dio.get("/init/download").then((value) => Navigator.pushReplacement(
// context, MaterialPageRoute(builder: (context) => LoginPage())));
// Future.delayed(Duration(seconds: 5), () {
// Navigator.pushReplacement(
// context, MaterialPageRoute(builder: (context) => LoginPage()));
// });
}
void myInit() async {
// 1. 외부 API 연결하기 (소켓 - 알림)
await dio.get("/init/download");
// if 로컬에 존재하는지 체크
// 2. 20MB 무거운 데이터 (다운로드)
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => LoginPage()));
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Image.asset(
'assets/splash.gif',
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
),
),
);
}
}
JavaScript
복사
import 'package:flutter/material.dart';
import 'package:flutter_blog/_core/constants/http.dart';
import 'package:flutter_blog/ui/pages/auth/login_page/login_page.dart';
class SplashTestPage extends StatefulWidget {
const SplashTestPage({super.key});
@override
State<SplashTestPage> createState() => _SplashTestPageState();
}
class _SplashTestPageState extends State<SplashTestPage> {
@override
void initState() {
super.initState();
myInit();
// dio.get("/init/download").then((value) => Navigator.pushReplacement(
// context, MaterialPageRoute(builder: (context) => LoginPage())));
// Future.delayed(Duration(seconds: 5), () {
// Navigator.pushReplacement(
// context, MaterialPageRoute(builder: (context) => LoginPage()));
// });
}
void myInit() async {
// 1. 외부 API 연결하기 (소켓 - 알림)
await dio.get("/init/download");
// if 로컬에 존재하는지 체크
// 2. 20MB 무거운 데이터 (다운로드)
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => LoginPage()));
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Image.asset(
'assets/splash.gif',
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
),
),
);
}
}
JavaScript
복사
Future<ResponseDTO> fetchAutoLogin(String accessToken) async {
Response response = await dio.post("/auto/login",
options: Options(headers: {"Authorization": "$accessToken"}));
Logger().d(response.data);
ResponseDTO responseDTO = ResponseDTO.fromJson(response.data);
if (responseDTO.success) {
responseDTO.response = User.fromJson(responseDTO.response);
return responseDTO;
}
return responseDTO;
}
JavaScript
복사
Future<void> autoLogin() async {
// secureStorage는 앱삭제시에 사라짐
String? accessToken = await secureStorage.read(key: "accessToken");
if (accessToken == null) {
Navigator.of(mContext!).pushNamed(Move.loginPage);
} else {
ResponseDTO responseDTO =
await UserRepository().fetchAutoLogin(accessToken);
if (responseDTO.success) {
super.user = responseDTO.response;
super.accessToken = accessToken;
super.isLogin = true;
Navigator.popAndPushNamed(mContext!, Move.postListPage);
} else {
Navigator.popAndPushNamed(mContext!, Move.loginPage);
}
}
}
JavaScript
복사
import 'package:flutter/material.dart';
import 'package:flutter_blog/data/store/session_store.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class SplashPage extends ConsumerWidget {
const SplashPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
ref.read(sessionProvider).autoLogin();
return Scaffold(
body: Center(
child: Image.asset(
'assets/splash.gif',
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
),
),
);
}
}
JavaScript
복사
Future<void> logout() async {
super.user = null;
super.accessToken = null;
super.isLogin = false;
await secureStorage.delete(key: "accessToken");
Navigator.popAndPushNamed(mContext!, Move.loginPage);
}
JavaScript
복사
import 'package:flutter/material.dart';
import 'package:flutter_blog/_core/constants/move.dart';
import 'package:flutter_blog/_core/constants/size.dart';
import 'package:flutter_blog/data/store/session_store.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class CustomNavigation extends ConsumerWidget {
final scaffoldKey;
const CustomNavigation(this.scaffoldKey, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
return Container(
width: getDrawerWidth(context),
height: double.infinity,
color: Colors.white,
child: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Consumer(
builder: (context, ref, child) {
return TextButton(
onPressed: () {
scaffoldKey.currentState!.openEndDrawer();
Navigator.pushNamed(context, Move.postWritePage);
},
child: const Text(
"글쓰기",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.black54,
),
),
);
},
),
const Divider(),
TextButton(
onPressed: () {
scaffoldKey.currentState!.openEndDrawer();
ref.read(sessionProvider).logout();
},
child: const Text(
"로그아웃",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.black54,
),
),
),
const Divider(),
],
),
),
),
);
}
}
JavaScript
복사