gpt4 book ai didi

flutter - 如何刷新 Flutter 应用程序仪表板上的计数值? (遵循 BLoC 模式)

转载 作者:行者123 更新时间:2023-12-05 07:08:21 25 4
gpt4 key购买 nike

enter image description here

对于如图所示的仪表板设计,我必须显示从 API 获取的各种计数。每个计数都将通过查看标签从不同的 API 获取。

我开发的结构,

  • DashboardScreen
    • CustomBottomMenuOptionWidget (标签)- StatelessWidget
      • MenuCountPage (标签)- StatefulWidget (为了显示计数,我根据标签采用了单独的 MenuCountScreen 小部件及其自己的 eventstatebloc)

当应用程序打开时,一切正常。对于每个不同的菜单选项,我都可以获得每个标签的计数。我的主要问题是用户在应用程序中前进并创建一个新事件,当返回仪表板时,我如何刷新此计数或简单地说我如何将事件添加到 BLoCMenuCountScreen获得更新值?

当前实现:

dashboard.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);
}
}
}

我已经尝试过的事情:

  1. 提供 BLoC来自父级(来自“仪表板”)并且当用户返回仪表板时尝试添加事件以获取更新计数。没用。 (如果是因为我有不同的基于标签的 API 调用并且每个计数都与其自己的 MenuCountBloc 实例相关联 - 如果我错了请清除我)

  2. 尝试拍摄 bool值并将其传递给 MenuCountScreen来自 Dashboard当用户返回仪表板时,更新 bool 的值认为它会刷新并再次调用事件但没有奏效。

  3. 除了尝试过的选项 1,取 4 个不同的 intBLoC 中存储 4 个不同计数的参数以及 MenuCountState .以为它会为 BLoC 存储 4 个值我从 Dashboard 提供的.但没有成功。

    我想知道,我的实现方式是否正确以及我尝试过的事情。也是一种可能的解决方案,可以在我遇到困难时完成我的任务。

已编辑:我在此处推送的示例项目:GitHub

最佳答案

所以基本上你是在说'当你回到旧屏幕时如何更新值?'

与 BLoC 无关,但与Navigators 相关。

如果您注意到,您会看到每个 Navigator.push 函数都返回一个 future 。基本上您可以等待直到您进入下一个屏幕。

当您从下一个屏幕弹出时,您可以来到第一个屏幕,您的 Navigator.push 会告诉您下一个屏幕已关闭。

让我们看一些代码。

class _AState extends State<A> {
void gotoB() async {
await Navigator.push(context, MaterialPageRoute(builder: (context) => B()));
refreshScreen();
}

void refreshScreen() {
// Call BLoC functions to update the screen
}

@override
Widget build(BuildContext context) {
return Container();
}
}

class B extends StatefulWidget {
@override
_BState createState() => _BState();
}

class _BState extends State<B> {
completeWork() {
Navigator.pop(context);
}

@override
Widget build(BuildContext context) {
return Container();
}
}

A类我要去B类。我在Navigator前面使用await等待我从B回来。

当我在执行 Navigator.pop() 时从 B 返回到 A。来到这里后,我正在刷新我的屏幕 A

关于flutter - 如何刷新 Flutter 应用程序仪表板上的计数值? (遵循 BLoC 模式),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61889399/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com