-
[Flutter] Service locator pattern을 사용해 build context 없이 navigate 하기웹 개발/Flutter 2021. 1. 31. 01:01반응형
아래의 flutter web의 routing을 배우기 전에
get it package의 Service locator을 사용한 navigation 방법에 대해 익혀보려고 한다.
Service locator pattern
서비스 중개자(Service locator) 는 서비스 제공자를 등록하고, 서비스를 사용하는 측에서 이 서비스에 접근할 수 있도록 중개해준다. 서비스 제공자의 실제 자료형과 이를 등록하는 과정은 숨긴다.
출처 : http://hajeonghyeon.blogspot.com/2017/06/service-locator-pattern.htmlwww.filledstacks.com/post/navigate-without-build-context-in-flutter-using-a-navigation-service/
1) Service locator 등록
- locator.dart
GetIt locator = GetIt.instance; void setupLocator() { locator.registerLazySingleton(() => NavigationService()); }
get it package를 통해 서비스 제공자인 navigation_service를 등록한다.
lazy singleton 혹은 factory을 이용하여 전역적으로 접근이 가능하도록 한다.
get_it package에 대한 포스팅
https://seizemymoment.tistory.com/482) 서비스 제공자 정의
- navigation_service.dart
class NavigationService { final GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>(); Future<dynamic> navigateTo(String routeName) { return navigatorKey.currentState.pushNamed(routeName); } bool goBack() { return navigatorKey.currentState.pop(); } }
서비스 제공자인 navigation_service를 정의한다.
navigation_service는 global key를 이용해서 navigatorKey가 있는 widget에 접근하고 state를 바꾼다.
* navigatorKey.currentState - global key가 있는 tree내 widget에 대한 state
key 사용에 대한 설명
https://nsinc.tistory.com/214
https://stackoverflow.com/questions/50080860/what-are-keys-in-the-stateless-widgets-class
global key에 대한 설명
global key는 전체 앱에서 고유한 key이며 element를 고유하게 식별한다.
특정 위젯의 정보를 완전히 다른 위젯트리 (예: 빌드 컨텍스트) 에서 접근가능하게 하며
StatefulWidgets의 경우 State에 대한 액세스 권한도 제공해 위젯이 상태를 잃지 않으면서
부모를 바꿀 수 있도록 해준다.
https://api.flutter.dev/flutter/widgets/GlobalKey-class.html
https://nsinc.tistory.com/2143) Service locator와 어플리케이션 연결
- main.dart
class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( ... navigatorKey: locator<NavigationService>().navigatorKey, onGenerateRoute: router.generateRoute, initialRoute: routes.LoginRoute, ); } }
main.dart에서 navigator key를 설정함으로 service locator와 어플리케이션을 연결한다.
onGenerateRoute와 initialRoute를 통해서 초기 route를 설정한다.
4) route에 대한 정의
- router.dart
Route<dynamic> generateRoute(RouteSettings settings) { switch (settings.name) { case routes.LoginRoute: return MaterialPageRoute(builder: (context) => LoginView()); case routes.HomeRoute: return MaterialPageRoute(builder: (context) => HomeView()); default: return MaterialPageRoute( builder: (context) => Scaffold( body: Center( child: Text('No path for ${settings.name}'), ), ), ); } }
routing에 대한 포스팅
seizemymoment.tistory.com/515) Navigation Service 사용하기
1) Service locator로부터 NavigationService type을 확인한다.
final NavigationService _navigationService = locator<NavigationService>();
2) NavigationService에 접근하여 route를 이동한다.
_navigationService.navigateTo(routes.HomeRoute);
< 예시 >
class LoginView extends StatelessWidget { const LoginView({Key key}) : super(key: key); @override Widget build(BuildContext context) { return ChangeNotifierProvider( builder: (context) => LoginViewModel(), child: Consumer<LoginViewModel>( builder: (context, model, child) => Scaffold( body: Padding( padding: const EdgeInsets.only(bottom: 25.0), child: Align( alignment: Alignment.bottomCenter, child: GestureDetector( onTap: () async { var success = await model.login(success: true); if (success) { Navigator.of(context).pushNamed(routes.HomeRoute); } }, ...
import 'package:nav_service/constants/route_paths.dart' as routes; import 'package:nav_service/services/navigation_service.dart'; ... class LoginViewModel extends BaseModel { final NavigationService _navigationService = locator<NavigationService>(); Future login({bool success = true}) async { setBusy(true); await Future.delayed(Duration(seconds: 1)); if (!success) { setErrorMessage('Error has occured with the login'); } else { _navigationService.navigateTo(routes.HomeRoute); setErrorMessage(null); } setBusy(false); } }
이 방법의 이점은 UI는 그대로 유지되고 모델이 모든 논리/상태 관리를 수행할 수 있다는 이점이 있다.
반응형'웹 개발 > Flutter' 카테고리의 다른 글
[Flutter Web] Fluro 패키지로 네비게이션 라우팅하기 ( Deep link / Transitions) (1) 2021.02.11 [Web] 안드로이드 스튜디오에서 웹 실행시 포트 지정(설정) 하는 법 (0) 2021.02.07 [Flutter] 플러터 종속성 주입 (InheritedWidgets/ get_it / provider) (0) 2021.01.28 [Flutter] 플러터 웹 사이트 반응형으로 생성하기 (1) 2021.01.23 [Flutter] 플러터 웹 프로젝트 생성 (0) 2021.01.23