이번에는 auth page 에서 인증 성공후 Home Screen 으로 이동하는 기능을 추가해보겠습니다
(실제 사용자관리는 차후 예정).
개발환경 : 윈도우11, 안드로이드 스튜디오, flutter 3.0.1
기존에 네비게이션을 beamer 와 getx 로 이중으로 진행하였는데, beamer 보다 getx 가 가성비가 좋은거 같아서 이후로는 getx 로 네비게이션을 구현할 예정입니다.
특히, beamer 의 BeamGuard 의 기능은 GetX 에서는 middlewares 로 구현 가능하다.
그래서 상태관리도 GetX 로 구현할 예정입니다.
화면 흐름은 아래와 같다.
./src/apple_app.dart - refactorying 및 initialBinding 추가
import 'package:beamer/beamer.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:provider/provider.dart';
import 'bindings/init_binding.dart';
import 'constants/common_size.dart';
import 'router/locations.dart';
import 'screens/start_screen.dart';
import 'states/user_state.dart';
// beamer 관련
final _routerDelegate = BeamerDelegate(
guards: [
BeamGuard(
// '/' 루트 페이지로 이동을 시도하기 전에 check 를 확인하고
// check 의 리턴값이 ture 면 계속 진행(루트 페이지/HomeScreen() 으로 이동)
// check 의 리턴값이 false 면 beamToNamed 으로 이동, '/auth'(AuthLocation) 으로 이동
pathPatterns: ['/'],
check: (context, location) {
return context.watch<UserProvider>().userState;
// return context.watch<UserNotifier>().user != null;
},
beamToNamed: (origin, target) => '/auth',
// showPage: BeamPage(child: StartScreen()),
)
],
locationBuilder: BeamerLocationBuilder(beamLocations: [
HomeLocation(),
AuthLocation(), // 이게 없으면 beamToNamed 이동시 오류 발생함
]),
);
class AppleApp extends StatelessWidget {
AppleApp({Key? key}) : super(key: key);
// themeData 공통사용하기 위해서
final themeData = ThemeData(
primarySwatch: Colors.red,
// 이걸 대표로 설정하면 기본 분위기가 유사하게 적용
fontFamily: 'Dohyeon',
// 배달의민족 도현체
hintColor: Colors.grey[350],
textTheme: const TextTheme(
headline3: TextStyle(
fontFamily: 'Dohyeon',
fontWeight: FontWeight.bold,
color: Colors.blue,
),
button: TextStyle(color: Colors.white),
subtitle1: TextStyle(color: Colors.black87, fontSize: 15),
subtitle2: TextStyle(color: Colors.grey, fontSize: 13),
bodyText1: TextStyle(
color: Colors.black87, fontSize: 12, fontWeight: FontWeight.normal),
bodyText2: TextStyle(
color: Colors.black54, fontSize: 12, fontWeight: FontWeight.w100),
),
// inputDecorationTheme: const InputDecorationTheme(
// enabledBorder: UnderlineInputBorder(
// borderSide: BorderSide(color: Colors.transparent),
// ),
// ),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
backgroundColor: Colors.red,
primary: Colors.white,
minimumSize: const Size(10, 48)),
),
appBarTheme: const AppBarTheme(
backgroundColor: Colors.white,
foregroundColor: Colors.black87,
elevation: 2,
titleTextStyle: TextStyle(color: Colors.black87),
actionsIconTheme: IconThemeData(color: Colors.black87),
),
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
selectedItemColor: Colors.black87,
unselectedItemColor: Colors.black54,
),
);
@override
Widget build(BuildContext context) {
// 여기에서 라우팅 방식을 설정함
if (routerType == RouterType.beamer) {
// beamer 라우팅시 설정방법
return beamRouter(context);
}
// getx 라우팅시 설정방법
return getRouter();
}
// getx 라우팅시 설정방법
GetMaterialApp getRouter() {
return GetMaterialApp(
debugShowCheckedModeBanner: false,
title: 'Apple Market Demo',
theme: themeData,
getPages: getPages(),
// 전체에 필요한 Controller 를 초기 binding 에 추가함
initialBinding: BindingInjection(),
);
}
// beamer 라우팅시 설정방법
ChangeNotifierProvider<UserProvider> beamRouter(BuildContext context) {
return ChangeNotifierProvider<UserProvider>(
create: (BuildContext context) => UserProvider(),
child: MaterialApp.router(
debugShowCheckedModeBanner: false,
title: 'Apple Market Demo',
theme: themeData,
routeInformationParser: BeamerParser(),
routerDelegate: _routerDelegate,
),
);
}
}
./src/middleware/check_auth.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../states/user_state.dart';
class CheckAuth extends GetMiddleware {
@override
int? get priority => 2;
bool isAuthenticated = false;
@override
RouteSettings? redirect(String? route) {
// injection & binding
Get.put(UserController());
isAuthenticated = UserController.to.userState.value;
if (isAuthenticated == false) {
return const RouteSettings(name: '/auth');
}
return null;
}
}
./src/screens/start/auth_page.dart - 주요 수정은 attemptVarify() 함수 관련 부분
void attemptVarify(BuildContext context) async {
setState(() {
// 인증 진행중
_verificationStatus = VerificationStatus.verifying;
});
debugPrint('_verificationStatus(attemptVarify): $_verificationStatus');
// 강제 딜레이 추가
await Future.delayed(const Duration(seconds: 2));
setState(() {
// 인증 완료
_verificationStatus = VerificationStatus.verificationDone;
});
if(routerType == RouterType.beamer){
context.read<UserProvider>().setUserAuth(true);
debugPrint('*** userState(attemptVarify): ${context.read<UserProvider>().userState}');
} else {
UserController.to.setUserAuth(true);
Get.toNamed('/');
}
debugPrint('_verificationStatus(attemptVarify): $_verificationStatus');
}
./src/bindings/init_binding.dart - 유저 정보는 모든 곳에서 접근해야하므로 initialBinding 에 추가
import 'package:get/get.dart';
import '../states/user_state.dart';
class BindingInjection implements Bindings {
@override
void dependencies() {
// TODO: implement dependencies
Get.put(UserController());
}
}
./src/states/user_state.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class UserController extends GetxController {
static UserController get to => Get.find();
final RxBool _userLoggedIn = false.obs;
RxBool get userState => _userLoggedIn;
void setUserAuth(bool authState) {
_userLoggedIn(authState);
}
}
class UserProvider extends ChangeNotifier {
bool _userLoggedIn = false;
bool get userState => _userLoggedIn;
void setUserAuth(bool authState) {
_userLoggedIn = authState;
notifyListeners();
}
}
'Flutter > 12 Clone 'Used Goods app'' 카테고리의 다른 글
[Flutter] Clone - 당근마켓10(Address Model) (0) | 2022.07.22 |
---|---|
[Flutter] Clone - 당근마켓9(logout) (0) | 2022.07.21 |
[Flutter] Clone - 당근마켓7(PageView - auth page) (0) | 2022.07.20 |
[Flutter] Clone - 당근마켓6(PageView - address page) (0) | 2022.07.19 |
[Flutter] Clone - 당근마켓5(PageView - intro page) (0) | 2022.07.15 |