개발아빠/Flutter

플러터(Flutter)에서 Fluro 사용하여 Router 설정하기

육아개발아빠 2020. 11. 5. 14:15
반응형

 

안녕하세요.

개발아빠입니다.

 

오늘은 Flutter에서 Fluro 라이브러리를 사용해서 라우터를 설정하여 화면을 이동하는 것을 간단하게 진행해보려고합니다.

기본적으로 Router설정에 대해서 모르시는 분들은 아래 글을 먼저 보고 와주세요.

 

2020/09/28 - [개발아빠/Flutter] - 플러터(Flutter) 화면 이동을 위한 Router(라우터) 설정 하기

2020/09/29 - [개발아빠/Flutter] - 플러터(Flutter) 화면 이동 시 데이터 넘기기

 

먼저 이것을 진행하게 된 이유에 대해서 먼저 간단히 살펴보면요. (말이 길어질꺼같지만요)

네이티브 앱에서는 크게 이슈가 없었는데 플러터로 웹까지 같이 하고 있다보니 문제가 되는 것이 생기더라구요. 

웹에서는 앱과는 다르게 브라우저의 주소창을 통해 접근이 가능하다보니, 

 

예를들어,

목록에서 상세로 이동을 해줄 경우에,

 

네이티브앱에서는 기존 글들에서의 데이터를 넘겨주면 되었고, 이건 제가 통제가 되었지만,

웹에서는 주소가 보이기에 상세로 곧바로 진입을 하려고 할지도 모릅니다. 

그렇게 되었을때는 기존 글들에서 데이터를 넘기는 방식들이 무의미해지는것이죠~ 

왜냐하면 데이터를 넘겨야 동작을 하기 때문이죠~

class MainPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title: new Text("Fluro 메인"),
      ),
      body: Container(
        child: Center(
          child: RaisedButton(
            child: Text('상세로 이동'), onPressed: () {
            Navigator.of(context).pushNamed(Routes.detail, arguments: {"id" : 1});
          },
          ),
        ),
      ),
    );
  }
}
class _DetailPageState extends State<DetailPage> {

  int id;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    final Map arguments = ModalRoute.of(context).settings.arguments as Map;
    if (arguments != null) {
      id = arguments["id"] as int;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title: new Text("Fluro 상세"),
      ),
      body: Container(
        child: Center(
          child: Text(id.toString()),
        ),
      ),
    );
  }
}

일반적인 방식으로 데이터를 넘기면 앱 과 웹에서 잘 동작합니다~

그런데 웹에서는 주소창이 있기에 

디테일 화면으로 가면 path 가 /#/detail 있고 이걸 다시 호출하게 되면 

앞에서 넘겨준 데이터가 없기때문에 id가 null로 됩니다~ 실제로 id를 받아와서 무언가를 할려 할때

웹에서는 이렇게 중간에서 치고(?) 들어올 수 있기에 문제가 생겨버립니다.

 

이런 문제들로 인해서 수소문(?)을 해보다가 Fluro를 찾게 되어서 사용하게 되었습니다. 

Fluro를 통해 이 문제들을 해결해보시죠~

dependencies:
  fluro: ^1.7.7
class FRouter {
  static FluroRouter router = FluroRouter();

  static const String detail = '/detail/:id';

  static void setupRouter() {
    router.define(detail, handler: detailHandler, transitionType: TransitionType.fadeIn);
  }
}

라우터를 추가해줍니다. 

다른부분보다 중요한 부분이 define입니다. 

 

첫번째는 route path이고, 두번째는 핸들러, 세번째는 화면 변동시에 애니메이션입니다.

 

그리고 핸들러는 아래와 같이 추가해줍니다. 

var detailHandler = Handler(
    handlerFunc: (BuildContext context, Map<String, dynamic> params) {
      return DetailPage(params['id'][0]);
    });

기존과 다르게 argument에 데이터를 넣은게 아니라 Page에 변수를 넘겼기 때문에 DetailPage도 변경해줍니다. 

class DetailPage extends StatefulWidget {

  final String id;

  DetailPage(this.id);

  @override
  _DetailPageState createState() => _DetailPageState();
}

class _DetailPageState extends State<DetailPage> {


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title: new Text("Fluro 상세"),
      ),
      body: Container(
        child: Center(
          child: Text(widget.id),
        ),
      ),
    );
  }
}

그리고 버튼에 아래와 같이 변경하면,

FRouter.router.navigateTo(context, FRouter.detail.replaceAll(":id", "1"));

될줄알았는데,

No registered route was found to handle '/detail/1'.

 

에러가 발생하네요~

 

main.dart에 아래와 같이 추가하는걸 잊지마세요.

void main() {
  FRouter.setupRouter();
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      onGenerateRoute: FRouter.router.generator,
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MainPage(),
    );
  }
}

FRouter.setupRouter();

onGenerateRoute: FRouter.router.generator,

를 추가하였습니다.

 

이렇게 하시면 정상 작동하시는게 확인되실겁니다.

 

그러면 웹에서의 실제 Url Path를 확인해볼께요~

Url Path가 detail/1 로 변경되었습니다. 

이제 굳이 앞페이지를 거치지 않고도 해당 페이지로 이동 할 수 있게 되었네요.

 

추가적으로 Fluro를 사용하면 Arguments로도 보내는것도 가능하구요.

/// Push a route with custom RouteSettings if you don't want to use path params
FluroRouter.appRouter.navigateTo(
  context,
  'home',
  routeSettings: RouteSettings(
    arguments: MyArgumentsDataClass('foo!'),
  ),
);

/// Extract the arguments using [BuildContext.settings.arguments] or [BuildContext.arguments] for short
var homeHandler = Handler(
  handlerFunc: (context, params) {
    final args = context.settings.arguments as MyArgumentsDataClass;

    return HomeComponent(args);
  },
);

화면 이동의 Transition 설정이 간편하게 할 수 있어서 좋았던거같아서. 현재 사이드 프로젝트에서도 잘 사용중입니다.

Router쪽은 Flour 사용해보시는것도 추천드리며, 

오늘의 내용은 마치겠습니다.

 

반응형