티스토리 뷰
Flutter 애플리케이션을 개발하면서 화면 간 데이터를 전달해야 하는 경우가 자주 있습니다. 이번 블로그에서는 Flutter의 Navigator와 arguments를 활용해 데이터를 전달하고 관리하는 방법을 심도 있게 알아보겠습니다.
참고. Pass arguments to a named route
Flutter에서 Navigator와 arguments란?
Flutter의 Navigator는 화면 간 전환을 관리하는 핵심 도구입니다. Navigator는 스택(stack) 구조를 사용해 화면을 추가하거나 제거하며, 이를 통해 간단하고 직관적인 화면 전환을 제공합니다.
arguments는 화면 전환 시 데이터를 전달할 수 있는 속성으로, 이를 활용하면 화면 간 데이터를 쉽게 공유할 수 있습니다.
Flutter에서 데이터를 전달하는 단계
1. 전달할 데이터 정의
전달하고자 하는 데이터를 담는 클래스를 생성합니다. 이 클래스는 전달할 데이터의 구조를 정의합니다.
class ScreenArguments {
final String title;
final String message;
ScreenArguments(this.title, this.message);
}
2. 데이터를 전달받는 화면 구성
데이터를 전달받아 화면에 표시할 위젯을 작성합니다. ModalRoute.of(context)!를 사용해 전달된 데이터를 추출합니다.
class ExtractArgumentsScreen extends StatelessWidget {
static const routeName = '/extractArguments';
@override
Widget build(BuildContext context) {
final args = ModalRoute.of(context)!.settings.arguments as ScreenArguments;
return Scaffold(
appBar: AppBar(title: Text(args.title)),
body: Center(child: Text(args.message)),
);
}
}
3. routes에 화면 등록
MaterialApp 위젯의 routes
속성에 화면을 등록합니다.
MaterialApp(
routes: {
ExtractArgumentsScreen.routeName: (context) => ExtractArgumentsScreen(),
},
);
4. 데이터와 함께 화면 전환
화면 전환 시 데이터를 Navigator.pushNamed()
의 arguments
속성을 통해 전달합니다.
Navigator.pushNamed(
context,
ExtractArgumentsScreen.routeName,
arguments: ScreenArguments(
'Hello Flutter!',
'This message is passed as arguments.',
),
);
onGenerateRoute로 동적 경로 처리하기
Flutter에서는 onGenerateRoute
를 사용해 더 유연한 경로 설정이 가능합니다. 이를 활용하면 동적으로 데이터를 처리하거나 조건에 따라 화면을 렌더링할 수 있습니다.
MaterialApp(
onGenerateRoute: (settings) {
if (settings.name == ExtractArgumentsScreen.routeName) {
final args = settings.arguments as ScreenArguments;
return MaterialPageRoute(
builder: (context) => ExtractArgumentsScreen(
title: args.title,
message: args.message,
),
);
}
return null;
},
);
Named Routes와 arguments의 장점
- 가독성: 명명된 경로를 사용하면 화면 전환을 보다 명확히 이해할 수 있습니다.
- 유지보수: 경로 이름을 중앙에서 관리하므로 코드 변경이 간단합니다.
- 유연성: 동적으로 데이터를 전달하거나 경로를 설정할 수 있습니다.
데이터 전달 시 주의점
- 데이터 타입 확인
- 전달된 데이터의 타입이 맞는지 확인해야 런타임 에러를 방지할 수 있습니다.
- 예외 처리
- 데이터를 받지 못했을 때를 대비해 기본값을 설정하거나 에러를 처리하는 코드를 작성하세요.
- 데이터 구조 관리
- 데이터 구조를 명확히 정의하고, 필요할 경우 JSON 또는 Map 형태로 데이터를 처리합니다.
Flutter의 데이터 전달 활용 사례
사례 1: 로그인 상태 전달
사용자가 로그인한 정보를 다음 화면으로 전달하여 개인화된 UI를 구성할 수 있습니다.
사례 2: 검색 조건 전달
검색 화면에서 설정한 필터 조건을 결과 화면으로 전달해 검색 결과를 필터링합니다.
사례 3: 다단계 폼 데이터 전달
다단계 폼에서 각 단계의 데이터를 다음 화면으로 전달해 최종적으로 데이터를 종합합니다.
결론
Flutter에서 Navigator와 arguments를 활용하면 화면 간 데이터 전달을 쉽게 처리할 수 있습니다. 이를 통해 애플리케이션의 유지보수성과 확장성을 높일 수 있으며, 복잡한 네비게이션 로직도 효율적으로 관리할 수 있습니다. 위에서 소개한 가이드를 참고해 Flutter 앱 개발에 적용해 보세요!
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
ExtractArgumentsScreen.routeName: (context) =>
const ExtractArgumentsScreen(),
},
// Provide a function to handle named routes.
// Use this function to identify the named
// route being pushed, and create the correct
// Screen.
onGenerateRoute: (settings) {
// If you push the PassArguments route
if (settings.name == PassArgumentsScreen.routeName) {
// Cast the arguments to the correct
// type: ScreenArguments.
final args = settings.arguments as ScreenArguments;
// Then, extract the required data from
// the arguments and pass the data to the
// correct screen.
return MaterialPageRoute(
builder: (context) {
return PassArgumentsScreen(
title: args.title,
message: args.message,
);
},
);
}
// The code only supports
// PassArgumentsScreen.routeName right now.
// Other values need to be implemented if we
// add them. The assertion here will help remind
// us of that higher up in the call stack, since
// this assertion would otherwise fire somewhere
// in the framework.
assert(false, 'Need to implement ${settings.name}');
return null;
},
title: 'Navigation with Arguments',
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home Screen'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// A button that navigates to a named route.
// The named route extracts the arguments
// by itself.
ElevatedButton(
onPressed: () {
// When the user taps the button,
// navigate to a named route and
// provide the arguments as an optional
// parameter.
Navigator.pushNamed(
context,
ExtractArgumentsScreen.routeName,
arguments: ScreenArguments(
'Extract Arguments Screen',
'This message is extracted in the build method.',
),
);
},
child: const Text('Navigate to screen that extracts arguments'),
),
// A button that navigates to a named route.
// For this route, extract the arguments in
// the onGenerateRoute function and pass them
// to the screen.
ElevatedButton(
onPressed: () {
// When the user taps the button, navigate
// to a named route and provide the arguments
// as an optional parameter.
Navigator.pushNamed(
context,
PassArgumentsScreen.routeName,
arguments: ScreenArguments(
'Accept Arguments Screen',
'This message is extracted in the onGenerateRoute '
'function.',
),
);
},
child: const Text('Navigate to a named that accepts arguments'),
),
],
),
),
);
}
}
// A Widget that extracts the necessary arguments from
// the ModalRoute.
class ExtractArgumentsScreen extends StatelessWidget {
const ExtractArgumentsScreen({super.key});
static const routeName = '/extractArguments';
@override
Widget build(BuildContext context) {
// Extract the arguments from the current ModalRoute
// settings and cast them as ScreenArguments.
final args = ModalRoute.of(context)!.settings.arguments as ScreenArguments;
return Scaffold(
appBar: AppBar(
title: Text(args.title),
),
body: Center(
child: Text(args.message),
),
);
}
}
// A Widget that accepts the necessary arguments via the
// constructor.
class PassArgumentsScreen extends StatelessWidget {
static const routeName = '/passArguments';
final String title;
final String message;
// This Widget accepts the arguments as constructor
// parameters. It does not extract the arguments from
// the ModalRoute.
//
// The arguments are extracted by the onGenerateRoute
// function provided to the MaterialApp widget.
const PassArgumentsScreen({
super.key,
required this.title,
required this.message,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Text(message),
),
);
}
}
// You can pass any object to the arguments parameter.
// In this example, create a class that contains both
// a customizable title and message.
class ScreenArguments {
final String title;
final String message;
ScreenArguments(this.title, this.message);
}
'Flutter Cookbook' 카테고리의 다른 글
Flutter에서 iOS Universal Links 설정하기: 딥 링크 구현 가이드 (2) | 2024.11.28 |
---|---|
Flutter에서 App Links 설정하기: Android 애플리케이션용 딥 링크 구성 가이드 (1) | 2024.11.27 |
Flutter에서 Named Route를 활용한 네비게이션 완벽 가이드 (0) | 2024.11.25 |
Flutter 내비게이션 기본 가이드: 화면 전환과 경로 관리 완벽 이해 (0) | 2024.11.24 |
Flutter로 멋진 Hero 애니메이션 구현하기: 화면 간 부드러운 전환 만들기 (0) | 2024.11.23 |