BottomNavigationBar с шаблоном BLoC
Мне очень нравится шаблон BLoC, и я пытаюсь понять его. Но я не могу понять, как именно это должно применяться с BottomNavigationBar
,
Создание списка страниц навигации и установка текущего индекса на событие касания панели навигации приводит к перерисовке всего приложения из-за setState()
,
Могу ли я использовать Navigator
показывать нажатую навигационную страницу, не теряя панель навигации?
Кто-нибудь использовал шаблон BLoC с BottomNavigationBar
? Как мне это сделать? Я хотел бы увидеть пример кода.
1 ответ
Я наконец получил это. Я помещаю весь код здесь, чтобы помочь другим.
Сначала прочитайте эту замечательную статью от Didier Boelens: https://www.didierboelens.com/2018/08/reactive-programming---streams---bloc/
используя его блок провайдера и базовый блок создавать блоки. моя похожа на следующее:
import 'dart:async';
import 'bloc_provider.dart';
import 'package:rxdart/rxdart.dart';
class NewsfeedBloc implements BlocBase {
BehaviorSubject<int> _ctrl = new BehaviorSubject<int>();
NewsfeedBloc(
// listen _ctrl event and do other business logic
);
void dispose() {
_ctrl.close();
}
}
затем создайте страницу, которая будет использовать блок:
import 'package:flutter/material.dart';
import '../blocs/newsfeed_bloc.dart';
import '../blocs/bloc_provider.dart';
class NewsfeedPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final NewsfeedBloc bloc = BlocProvider.of<NewsfeedBloc>(context);
// here you should use a stream builder or such to build the ui
return Container(
child: Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: Icon(Icons.album),
title: Text('The Enchanted Nightingale'),
subtitle: Text('Music by Julie Gable. Lyrics by Sidney Stein.'),
),
ButtonTheme.bar(
// make buttons use the appropriate styles for cards
child: ButtonBar(
children: <Widget>[
FlatButton(
child: const Text('BUY TICKETS'),
onPressed: () {/* do something with the bloc */},
),
FlatButton(
child: const Text('LISTEN'),
onPressed: () {/* do something with the bloc */},
),
],
),
),
],
),
),
);
}
}
и, наконец, файл main.dart, содержащий навигационную нижнюю панель и ящик:
import 'dart:async';
import 'package:flutter/material.dart';
import 'blocs/bloc_provider.dart';
import 'blocs/application_bloc.dart';
import 'blocs/newsfeed_bloc.dart';
import 'blocs/tracking_bloc.dart';
import 'blocs/notifications_bloc.dart';
import 'blocs/item1_bloc.dart';
import 'blocs/item2_bloc.dart';
import 'pages/newsfeed.dart';
import 'pages/tracking.dart';
import 'pages/notifications.dart';
import 'pages/item1.dart';
import 'pages/item2.dart';
Future<void> main() async {
return runApp(BlocProvider<ApplicationBloc>(
bloc: ApplicationBloc(),
child: MyApp(),
));
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
// define your blocs here so that you dont lose the state when your app rebuilds for some reason. thanks boformer for pointing that out.
NewsfeedBloc _newsfeedBloc;
PageController _pageController;
var _page = 0;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Movies',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: new Scaffold(
appBar: AppBar(
title: new Text('App Title'),
),
body: PageView(
children: <Widget>[
BlocProvider<NewsfeedBloc>(
bloc: _newsfeedBloc(),
child: NewsfeedPage(),
),
// ...
],
controller: _pageController,
onPageChanged: onPageChanged,
),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.timeline),
title: Text("Timeline"),
),
BottomNavigationBarItem(
icon: Icon(Icons.art_track),
title: Text("Some Page"),
),
BottomNavigationBarItem(
icon: Icon(Icons.notifications),
title: Text("Notifications"),
),
],
onTap: navigationTapped,
currentIndex: _page,
),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text('Settings'),
decoration: BoxDecoration(
color: Colors.blue,
),
),
ListTile(
title: Text('Item 1'),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) {
return BlocProvider<Item1Bloc>(
bloc: Item1Bloc(),
child: Item1Page(),
);
}
},
),
ListTile(
title: Text('Item 2'),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) {
return BlocProvider<Item2Bloc>(
bloc: Item2Bloc(),
child: Item2Page(),
);
}
},
),
],
),
),
),
);
}
void navigationTapped(int page) {
_pageController.animateToPage(
page,
duration: Duration(milliseconds: 300),
curve: Curves.easeIn,
);
}
void onPageChanged(int page) {
setState(() {
this._page = page;
});
}
@override
void initState() {
super.initState();
_pageController = new PageController();
_newsfeedBloc = NewsfeedBloc();
}
@override
void dispose() {
super.dispose();
_pageController.dispose();
}
}