对于如图所示的仪表板设计,我必须显示从 API 获取的各种计数。每个计数都将通过查看标签从不同的 API 中获取。
我开发的结构,
DashboardScreen
CustomBottomMenuOptionWidget
(标签) -StatelessWidget
MenuCountPage
(label) -StatefulWidget
(为了显示计数,我MenuCountScreen
使用了单独的小部件event
,并根据标签使用state
& )bloc
当应用程序打开时,一切正常。对于每个不同的菜单选项,我可以获得每个标签的计数。我的主要问题是用户在应用程序中前进并创建一个新事件,当返回仪表板时,我如何刷新此计数或简单地说我如何将事件添加到BLoC
以MenuCountScreen
获得更新的值?
当前实施:
仪表板.dart (GridView)
GridView.count(
primary: false,
padding: const EdgeInsets.all(20),
crossAxisSpacing: 20,
mainAxisSpacing: 20,
crossAxisCount: 2,
childAspectRatio: 1.3,
children: <Widget>[
HomeBottomGridMenuItem(
label: kMenuLabelCalendar,
onItemClick: () {
_onTapHomeMenuItem(context, kMenuLabelCalendar);
},
icon: ICON_CALENDAR,
itemCountExist: true,
itemCount: 10,
),
...other menu item
)
HomeBottomGridMenuItem.dart
import 'package:flutter/material.dart';
import 'package:flutter_app/resources/colors.dart';
import 'package:flutter_app/screens/dashboard/menu_count/menu_count.dart';
class HomeBottomGridMenuItem extends StatelessWidget {
final String label;
final String icon;
final Function onItemClick;
final bool itemCountExist;
final int itemCount;
HomeBottomGridMenuItem({
this.label,
this.icon,
this.onItemClick,
this.itemCountExist,
this.itemCount,
});
@override
Widget build(BuildContext context) {
return Stack(
fit: StackFit.expand,
children: <Widget>[
InkWell(
onTap: onItemClick,
splashColor: Colors.black26,
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey,
),
borderRadius: BorderRadius.all(
Radius.circular(
8.0,
),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Image.asset(
icon,
height: 40.0,
width: 40.0,
color: kColorDashboardMenuItemIcon,
),
Text(
label,
textAlign: TextAlign.start,
style: Theme.of(context).textTheme.headline4.copyWith(
fontWeight: FontWeight.w400,
color: kColorDashboardMenuItemLabel,
),
)
],
),
),
),
Positioned(
top: 0,
right: 0,
child: Visibility(
visible: itemCountExist,
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 14.0,
vertical: 5.0,
),
decoration: BoxDecoration(
color: kColorAppPrimaryBlackShade,
borderRadius: BorderRadius.only(
topRight: Radius.circular(
5.0,
),
bottomLeft: Radius.circular(
5.0,
),
),
),
child: MenuCountPage(
label: label,
),
),
),
),
],
);
}
}
MenuCountPage.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'menu_count.dart';
class MenuCountPage extends StatelessWidget {
final String label;
MenuCountPage({
@required this.label,
});
@override
Widget build(BuildContext context) {
return BlocProvider<MenuCountBloc>(
create: (context) {
return MenuCountBloc(context: context);
},
child: MenuCountScreen(
menuLabel: label,
),
);
}
}
MenuCountScreen.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_app/widgets/loader_circular.dart';
import 'menu_count.dart';
class MenuCountScreen extends StatefulWidget {
final String menuLabel;
MenuCountScreen({
@required this.menuLabel,
});
@override
_MenuCountScreenState createState() => _MenuCountScreenState();
}
class _MenuCountScreenState extends State<MenuCountScreen> {
MenuCountBloc _menuCountBloc;
@override
void initState() {
_menuCountBloc = BlocProvider.of<MenuCountBloc>(context);
_menuCountBloc.add(
GetMenuCount(menuLabel: widget.menuLabel),
);
super.initState();
}
@override
Widget build(BuildContext context) {
return Center(
child: BlocBuilder<MenuCountBloc, MenuCountState>(
builder: (context, state) {
if (state is MenuCountSuccess) {
return Text(
'${state.count}',
style: Theme.of(context).textTheme.headline2.copyWith(
color: Colors.white,
),
);
}
if (state is MenuCountFail) {
return Text(
'0',
style: Theme.of(context).textTheme.headline2.copyWith(
color: Colors.white,
),
);
}
return CircularLoader(
size: 25,
strokeWidth: 3,
color: Colors.white60,
);
},
),
);
}
}
MenuCountEvent.dart
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
abstract class MenuCountEvent extends Equatable {
const MenuCountEvent();
}
class GetMenuCount extends MenuCountEvent {
final String menuLabel;
GetMenuCount({@required this.menuLabel});
@override
List<Object> get props => [];
}
MenuCountState.dart
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
abstract class MenuCountState extends Equatable {
const MenuCountState();
@override
List<Object> get props => [];
}
class MenuCountInitial extends MenuCountState {}
class MenuCountLoading extends MenuCountState {}
class MenuCountSuccess extends MenuCountState {
final int count;
MenuCountSuccess({@required this.count});
@override
List<Object> get props => [count];
}
class MenuCountFail extends MenuCountState {}
MenuCountBloc.dart
import 'package:chopper/chopper.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_app/api/api_service.dart';
import 'package:flutter_app/models/dashboard_count_responses/events_count_response.dart';
import 'package:flutter_app/models/dashboard_count_responses/open_ticket_count_response.dart';
import 'package:flutter_app/models/dashboard_count_responses/properties_count_response.dart';
import 'package:flutter_app/resources/strings.dart';
import 'package:flutter_app/utility/sharedpref_helper.dart';
import 'package:provider/provider.dart';
import 'menu_count.dart';
class MenuCountBloc extends Bloc<MenuCountEvent, MenuCountState> {
final BuildContext context;
MenuCountBloc({@required this.context});
@override
MenuCountState get initialState => MenuCountInitial();
@override
Stream<MenuCountState> mapEventToState(MenuCountEvent event) async* {
if (event is GetMenuCount) {
yield MenuCountLoading();
if (event.menuLabel.length > 0) {
yield* _getCountValueByLabel(event.menuLabel);
}
}
}
Stream<MenuCountState> _getCountValueByLabel(String menuLabel) async* {
switch (menuLabel) {
case kMenuLabelOpenTickets:
try {
final String token = await SharedPreferenceHelper.getToken();
final Response<OpenTicketCountResponse> apiResponse =
await Provider.of<ApiService>(context, listen: false)
.getOpenTicketCount(token);
if (apiResponse.isSuccessful) {
yield MenuCountSuccess(count: apiResponse.body.openTickets);
} else {
print('API : Response Failed');
yield MenuCountSuccess(count: 0);
}
} catch (exception) {
print('Exception: ${exception.toString()}');
yield MenuCountSuccess(count: 0);
}
break;
case kMenuLabelProperties:
try {
final String token = await SharedPreferenceHelper.getToken();
final Response<PropertiesCountResponse> apiResponse =
await Provider.of<ApiService>(context, listen: false)
.getPropertiesCount(token);
if (apiResponse.isSuccessful) {
yield MenuCountSuccess(count: apiResponse.body.properties_active);
} else {
print('API : Response Failed');
yield MenuCountSuccess(count: 0);
}
} catch (exception) {
print('Exception: ${exception.toString()}');
yield MenuCountSuccess(count: 0);
}
break;
case kMenuLabelCalendar:
try {
final String token = await SharedPreferenceHelper.getToken();
final Response<EventsCountResponse> apiResponse =
await Provider.of<ApiService>(context, listen: false)
.getEventsCount(token);
if (apiResponse.isSuccessful) {
yield MenuCountSuccess(count: apiResponse.body.events);
} else {
print('API : Response Failed');
yield MenuCountSuccess(count: 0);
}
} catch (exception) {
print('Exception: ${exception.toString()}');
yield MenuCountSuccess(count: 0);
}
break;
case kMenuLabelAllTickets:
try {
final String token = await SharedPreferenceHelper.getToken();
final Response<OpenTicketCountResponse> apiResponse =
await Provider.of<ApiService>(context, listen: false)
.getOpenTicketCount(token);
if (apiResponse.isSuccessful) {
yield MenuCountSuccess(count: apiResponse.body.tickets);
} else {
print('API : Response Failed');
yield MenuCountSuccess(count: 0);
}
} catch (exception) {
print('Exception: ${exception.toString()}');
yield MenuCountSuccess(count: 0);
}
break;
default:
yield MenuCountSuccess(count: 0);
}
}
}
我已经尝试过的事情:
由父(来自“仪表板”)提供
BLoC
,当用户返回仪表板时尝试添加事件以获取更新的计数。没用。(如果是因为我有基于标签的不同 API 调用,并且每个计数都与它自己的 MenuCountBloc 实例相关联 - 如果我错了,请清除我)尝试获取一个
bool
值并将其传递给MenuCountScreen
fromDashboard
,当用户返回仪表板时更新该值,bool
认为它会刷新并再次调用事件但没有奏效。除了尝试过的选项 1,采用 4 个不同的
int
参数来存储 4 个不同的计数BLoC
以及MenuCountState
.BLoC
以为它会为我提供的4 个值存储Dashboard
. 但没有奏效。我想知道,我的实现方式是否正确以及我尝试过的事情。也是一个可能的解决方案来完成我被卡住的任务。
编辑: 我推到这里的示例项目:GitHub