[Flutter] Bloc Access

김영진·2021년 12월 16일
0

목적

flutter_bloc 홈페이지 가보니 새로운 내용이 업데이트 되어 있길래 팔로우업 한다.
네비게이터를 태울때 블록을 어떻게 내려주면 좋을지 고민이 많았다. 왜냐하면 블록을 새로 만들면 상태공유가 안되기 때문에,어떻게 할지 고민이 있었는데
이 문서를 대강 훑었는데 그 내용이 상세히 설명되어있는것 같고 새로운 업데이트가 반가운 마음에 작성한다!

내용


로컬 엑세스

상단에서 내려주는 일반적인 방법
네비게이터 푸시, 팝이 없는 엑세스

app.dart

상태 내려주기

 home: BlocProvider(
        create: (BuildContext context) => CounterBloc(),
        child: CounterPage(),
      ),
counterPage.dart
이벤트 사용
final counterBloc = BlocProvider.of<CounterBloc>(context);

child: FloatingActionButton(
              child: Icon(Icons.add),
              onPressed: () {
                counterBloc.add(CounterIncrementPressed());
              },
            ),
자식위젯 넘어가기
 body: Center(
        child: CounterText(),
      ),
counterText.dart

특별한점 없이 일반적으로 사용하는방법 긴 설명없이 넘어가자

class CounterText extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return BlocBuilder<CounterBloc, int>(
      builder: (context, count) {
        return Text('$count');
      },
    );
  }
}

익명 경로 엑세스

app.dart

상태 내려줍니다

home: BlocProvider(
        create: (BuildContext context) => CounterBloc(),
        child: HomePage(),
      ),
homePage.dart

리턴하는 위젯에 BlocProvider.value(value:bloc, child: widget)을 래핑해서 넘겨주면 상태 제공 가능

child: ElevatedButton(
          onPressed: () {
            Navigator.of(context).push(
              MaterialPageRoute<CounterPage>(
                builder: (context) {
                  return BlocProvider.value(
                    value: counterBloc,
                    child: CounterPage(),
                  );
                },
              ),
            );
CounterPage.dart

하던것처럼 빌더로 상태 받아서 쓰면됨

class CounterPage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Counter'),
      ),
      body: BlocBuilder<CounterBloc, int>(
        builder: (context, count) {
          return Center(
            child: Text('$count'),
          );
        },
      ),
    );
  }
}

명명된 라우트 접근

app.dart

변수에 블록 생성자를 할당하고
상단 MaterialApp의 routes에 블록을 BlocProvider.value로 넘긴다.
생성자는 꼭 dispose해준다.

class _AppState extends State<App> {
  final _counterBloc = CounterBloc();

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      routes: {
        '/': (context) => BlocProvider.value(
              value: _counterBloc,
              child: HomePage(),
            ),
        '/counter': (context) => BlocProvider.value(
              value: _counterBloc,
              child: CounterPage(),
            ),
      },
    );
  }

  
  void dispose() {
    _counterBloc.close();
    super.dispose();
  }
}
HomePage.dart

그냥 네임드 네비게이터 태우면 됩니다.

child: ElevatedButton(
          onPressed: () => Navigator.of(context).pushNamed('/counter'),
          child: Text('Counter'),
        ),
CounterPage.dart

똑같음

class CounterPage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Counter'),
      ),
      body: BlocBuilder<CounterBloc, int>(
        builder: (context, count) {
          return Center(
            child: Text('$count'),
          );
        },
      ),
    );
  }

생성된 경로 엑세스

Router를 만들고 BlocProvider를 사용하여 다양한 generated routes에 접근한다. 라우터에서 우리가 원하는 범위에서 블록을 관리할것이고, 선택적으로 라우트에게 블록에 접근 권한을 줄것이다.

App.dart

라우터 생성하고 MaterialApp에 라우터 넘겨줌

class _AppState extends State<App> {
  final _router = AppRouter();

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      onGenerateRoute: _router.onGenerateRoute,
    );
  }

  
  void dispose() {
    _router.dispose();
    super.dispose();
  }
}
AppRouter.dart

블록 생성자로 생성해주고(디스포즈 꼭 해주고)
블록프로바이더 닷 벨류로 넘겨줌

class AppRouter {
  final _counterBloc = CounterBloc();

  Route onGenerateRoute(RouteSettings settings) {
    switch (settings.name) {
      case '/':
        return MaterialPageRoute(
          builder: (_) => BlocProvider.value(
            value: _counterBloc,
            child: HomePage(),
          ),
        );
      case '/counter':
        return MaterialPageRoute(
          builder: (_) => BlocProvider.value(
            value: _counterBloc,
            child: CounterPage(),
          ),
        );
      default:
        return null;
    }
  }

  void dispose() {
    _counterBloc.close();
  }
}
HomePage.dart

네임드 라우트 그냥 태우면 됩니다.

body: Center(
        child: ElevatedButton(
          onPressed: () => Navigator.of(context).pushNamed('/counter'),
          child: Text('Counter'),
        ),
      ),
CounterPage.dart

쓰면 됩니다 똑같음

body: BlocBuilder<CounterBloc, int>(
        builder: (context, count) {
          return Center(
            child: Text('$count'),
          );
        },
      ),

전역 접근

AuthenticationBloc 또는 ThemeBloc 과 같은 경우에 유용

App.dart

상태 내려줍니다
중요한점은 메터리얼앱 위에 올렸다

return BlocProvider(
      create: (BuildContext context) => CounterBloc(),
      child: MaterialApp(
        title: 'Flutter Demo',
        home: CounterPage(),
      ),
    );

사용

CounterText
class CounterText extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return BlocBuilder<CounterBloc, int>(
      builder: (context, count) {
        return Text('$count');
      },
    );
  }
}

결과

블록 접근 방법은
1. 로컬
2. 익명
3. 명명
4. 라우터
5. 전역
다섯가지 방법이 있고 기존엔 1,5를 적극적으로 사용했었다.
4번, 3번이 Navigator에 유연하게 대처할 수 있고 세련되어 보여서 리팩토링을 한번 진행해 봐야겠다.

profile
2021.05.03) Flutter, BlockChain, Sports, StartUp

0개의 댓글