我正在尝试在同一个小部件中更新数据,该小部件首先已加载数据。第二个窗口小部件添加到相同的数据,并同时显示更新后的数据来获取它。新数据未反映在第一个窗口小部件中。以购物车和商品数量为例。当我在购物车中添加新商品或更改数量时,它不会反映在购物车中。 所有数据都在Django Rest API中远程调用。 如果我重新加载该应用程序,新数据将显示在购物车中。
这是我要在其中更改数据的小部件
class MainScreen extends StatefulWidget {
final TokenResponse token;
const MainScreen({Key key, this.token});
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
BottomNavBarBloc _bottomNavBarBloc;
CartBloc cartBloc;
@override
void initState() {
_bottomNavBarBloc = BottomNavBarBloc();
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
cartBloc = BlocProvider.of<CartBloc>(context);
cartBloc.add(FetchOrderSummaryEvent());
return Scaffold(
backgroundColor: Colors.white,
body: AnnotatedRegion<SystemUiOverlayStyle>(
value: const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
),
sized: false,
child: StreamBuilder<NavBarItem>(
stream: _bottomNavBarBloc.itemStream,
initialData: _bottomNavBarBloc.defaultItem,
builder:
(BuildContext context, AsyncSnapshot<NavBarItem> snapshot) {
switch (snapshot.data) {
case NavBarItem.HOME:
return HomeScreen();
case NavBarItem.OFFERS:
return OffersScreen();
case NavBarItem.REWARDS:
return _testScreen();
case NavBarItem.FAVORITE:
return _testScreen();
case NavBarItem.BAG:
return CartScreen();
case NavBarItem.ACCOUNT:
return AccountMainScreen();
}
return Container();
}),
),
bottomNavigationBar: StreamBuilder(
stream: _bottomNavBarBloc.itemStream,
initialData: _bottomNavBarBloc.defaultItem,
builder: (BuildContext context, AsyncSnapshot<NavBarItem> snapshot) {
return BottomNavigationBar(
unselectedItemColor: Style.Colors.secondaryColor,
selectedItemColor: Style.Colors.primaryColor,
backgroundColor: Colors.white,
selectedFontSize: 10.0,
unselectedFontSize: 10.0,
type: BottomNavigationBarType.fixed,
currentIndex: snapshot.data.index,
onTap: _bottomNavBarBloc.pickItem,
items: [
BottomNavigationBarItem(
title: Padding(
padding: EdgeInsets.only(top: 5.0),
child: Text("Home"),
),
icon: Icon(
FontAwesomeIcons.bars,
color: Style.Colors.secondaryColor,
),
activeIcon: Icon(
FontAwesomeIcons.bars,
color: Style.Colors.primaryColor,
)),
BottomNavigationBarItem(
title: Padding(
padding: EdgeInsets.only(top: 5.0),
child: Text("Offers"),
),
icon: Icon(
FontAwesomeIcons.tag,
color: Style.Colors.secondaryColor,
),
activeIcon: Icon(
FontAwesomeIcons.tag,
color: Style.Colors.primaryColor,
)),
BottomNavigationBarItem(
title: Padding(
padding: EdgeInsets.only(top: 5.0),
child: Text("Rewards"),
),
icon: Icon(
FontAwesomeIcons.gift,
color: Style.Colors.secondaryColor,
),
activeIcon: Icon(
FontAwesomeIcons.gift,
color: Style.Colors.primaryColor,
)),
BottomNavigationBarItem(
title: Padding(
padding: EdgeInsets.only(top: 5.0),
child: Text("Favorite"),
),
icon: Icon(
FontAwesomeIcons.heart,
color: Style.Colors.secondaryColor,
),
activeIcon: Icon(
FontAwesomeIcons.heart,
color: Style.Colors.primaryColor,
)),
BottomNavigationBarItem(
title: Padding(
padding: EdgeInsets.only(top: 5.0),
child: Text("Bag"),
),
icon: Container(
width: 30,
height: 25,
child: Stack(children: <Widget>[
Icon(
FontAwesomeIcons.shoppingBag,
color: Style.Colors.secondaryColor,
),
BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (context, state) {
if (state is AuthenticationAuthenticated) {
return BlocBuilder<CartBloc, CartState>(
builder: (context, state) {
if (state is CartLoaded) {
print("loaded ${state.order.totalItemQuantity}"); // <=== change this data
return Positioned(
right: 0,
top: 0,
child: Container(
height: 20.0,
width: 20.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
border: Border.all(
width: 1.0,
color: Colors.white,
),
),
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
left: 1.0,
bottom: 1.0,
),
child: Text(
state.order.totalItemQuantity !=null? state.order.totalItemQuantity.toString():"",
style: TextStyle(
color: Colors.white,
fontSize: 10.0,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
);
} else {
return Container(
);
}
},
);
} else {
return Text(" ");
}
},
)
]),
),
activeIcon: Container(
width: 30,
height: 25,
child: Stack(children: <Widget>[
Icon(
FontAwesomeIcons.shoppingBag,
color: Style.Colors.primaryColor,
),
BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (context, state) {
if (state is AuthenticationAuthenticated) {
return BlocBuilder<CartBloc, CartState>(
builder: (context, state) {
if (state is CartLoaded) {
print("loaded ${state.order.totalItemQuantity}");
return Positioned(
right: 0,
top: 0,
child: Container(
height: 20.0,
width: 20.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
border: Border.all(
width: 1.0,
color: Colors.white,
),
),
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
left: 1.0,
bottom: 1.0,
),
child: Text(
state.order.totalItemQuantity !=null? state.order.totalItemQuantity.toString():"",
style: TextStyle(
color: Colors.white,
fontSize: 10.0,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
);
} else {
return Container(
);
}
},
);
} else {
return Text(" ");
}
},
)
]),
),),
BottomNavigationBarItem(
title: Padding(
padding: EdgeInsets.only(top: 5.0),
child: BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (context, state) {
if (state is AuthenticationAuthenticated) {
return Text("Account");
} else {
return Text("Login");
}
},
),
),
icon: Icon(
FontAwesomeIcons.user,
color: Style.Colors.secondaryColor,
),
activeIcon: Icon(
FontAwesomeIcons.user,
color: Style.Colors.primaryColor,
)),
],
);
},
),
);
}
Widget _testScreen() {
return Center(
child: Text(
'Test Screen',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.red,
fontSize: 25.0,
),
),
);
}
}
我在同级窗口小部件中调用API,这里我发布了从同级窗口小部件中按下按钮后调用的处理方法:
handleAddItemFromCart(
String slug, List<ItemVariations> itemVariations, BuildContext context) {
final cartBloc = BlocProvider.of<CartBloc>(context);
final currentState = cartBloc.state;
if( currentState is CartLoaded){
print("order quantity: ${currentState.order.totalItemQuantity.toString()}");
}
print("current state " + currentState.toString());
cartBloc.add(AddItemToCartEvent(
slug: slug, variations: formatVariations(itemVariations)));
cartBloc.add(FetchOrderSummaryEvent());
}
cart_event.dart
@immutable
abstract class CartEvent extends Equatable {
CartEvent([List props = const []]):super();
}
class FetchOrderSummaryEvent extends CartEvent {
FetchOrderSummaryEvent([List props = const[]]) : super(props);
Order order;
@override
List<Object> get props => [this.order];
}
class RemoveItemFromCartEvent extends CartEvent {
String slug;
List<int> variations;
RemoveItemFromCartEvent({@required this.slug, this.variations});
@override
List<Object> get props => [];
}
class AddItemToCartEvent extends CartEvent {
String slug;
List<int> variations;
AddItemToCartEvent({@required this.slug, @required this.variations});
@override
List<Object> get props => [];
}
class RemoveItemEvent extends CartEvent {
@override
List<Object> get props => [];
}
class CheckoutEvent extends CartEvent {
String stripeToken;
int selectedAddress;
CheckoutEvent({@required this.stripeToken, @required this.selectedAddress});
@override
List<Object> get props => [];
}
cart_state.dart
@immutable
abstract class CartState extends Equatable {
CartState([List props = const[]]):super();
@override
List<Object> get props => [];
}
class CartInitial extends CartState {
@override
// TODO: implement props
List<Object> get props => [];
}
class CartLoading extends CartState {
@override
// TODO: implement props
List<Object> get props => [];
}
class CartLoaded extends CartState {
Order order;
CartLoaded({@required this.order});
CartLoaded copyWith({Order order}) {
return CartLoaded(order: order ?? this.order);
}
@override
// TODO: implement props
List<Object> get props => [order];
}
class CartFailure extends CartState {
String message;
CartFailure({@required this.message});
@override
// TODO: implement props
List<Object> get props => [message];
}
cart_bloc.dart:
class CartBloc extends Bloc<CartEvent, CartState> {
MenuItemsRepository menuItemsRepository;
CartBloc({@required this.menuItemsRepository});
@override
// TODO: implement initialState
CartState get initialState => CartInitial();
@override
Stream<CartState> mapEventToState(CartEvent event) async* {
final currentState = state;
if (event is FetchOrderSummaryEvent) {
yield CartLoading();
try {
Order order = await menuItemsRepository.getOrder();
yield CartLoaded(order: order);
} catch (err) {
yield CartFailure(message: err.message);
}
}
if (event is AddItemToCartEvent) {
//yield CartLoading();
try {
await menuItemsRepository.addItemToCart(event.slug, event.variations);
} catch (err) {
yield CartFailure(message: err.toString());
}
}
if (event is RemoveItemFromCartEvent) {
yield CartLoading();
try {
await menuItemsRepository.removeItemFromCart(
event.slug, event.variations);
} catch (err) {
yield CartFailure(message: err.toString());
}
}
if (event is CheckoutEvent) {
yield CartLoading();
try {
print("token: ${event.stripeToken}");
await menuItemsRepository.makePayment(
event.stripeToken, event.selectedAddress);
} catch (err) {
yield CartFailure(message: err.toString());
}
}
}
}
存储库:
Future<bool> addItemToCart(String slug, List<int> variations) async {
final token = "Token " + await storage.read(key: utils.TOKEN);
var params = {
"slug": slug,
"variations": variations,
};
try {
Response response = await _dio.post(getAddToCartURL,
data: jsonEncode(params),
options: Options(headers: {
HttpHeaders.authorizationHeader: token,
HttpHeaders.contentTypeHeader: "application/json",
}));
return response.statusCode == 200;
} catch (error, stackTrace) {
print("Exception occurred: $error stackTrace: $stackTrace");
return false;
}
}
Future<Order> getOrder() async {
final token = "Token " + await storage.read(key: utils.TOKEN);
var params = {
"api_key": apiKey,
};
try {
Response response = await _dio.get(getOrderSummaryURL,
queryParameters: params,
options: Options(headers: {
HttpHeaders.authorizationHeader: token,
HttpHeaders.contentTypeHeader: "application/json",
}));
print(response.data);
return Order.fromJson(response.data);
} catch (error, stackTrace) {
print("Exception occurred: $error stackTrace: $stackTrace");
return Order.withError(error.toString());
}
}
答案 0 :(得分:0)
更新: 我想到了! 团体CartBloc实例化2次!一个在应用程序创建开始时开始,或者从main.dart文件开始,然后在子窗口小部件中另一个(即order_summary文件)开始。这导致无法强制父窗口小部件从api获取数据。因此所有更新都是在子级别而非父级别完成的。 我希望这将对可能遇到相同问题的任何人有所帮助。确保仅实例化该块一次,以便您可以更新或接收来自同一块的更新。