我希望有人能帮助我:) 我有一个 flutter 应用程序并使用 provider package 来管理状态。
我想要实现的目标: 当我单击按钮并删除订单时,我想通知我的按钮并提供 isLoading 值。当 isLoading == true 时,按钮应显示加载微调器并降低其不透明度。
目前状态如何: 当我单击按钮时,订单会被删除,但不透明度不会降低,加载微调器也不会显示。虽然我可以在按钮中访问 isLoading 。
这是我的 OrderService(商店):
import ...
class OrderService with ChangeNotifier {
final supabaseClient = Supabase.instance.client;
bool _isLoading = false;
bool get isLoading => _isLoading;
_toggleLoading() {
_isLoading = !_isLoading;
notifyListeners();
}
Future<void> deleteOrderWithId(int id, BuildContext context) async {
try {
_toggleLoading();
await supabaseClient.from('orders').delete().eq('id', id);
} catch (err) {
print(err);
} finally {
_toggleLoading();
}
}
Future<void> createOrderFromOrder(Order order, BuildContext context) async {...}
}
这是我的自定义按钮:
import ...
class TrustyButton extends StatelessWidget {
final void Function() onTap;
final String text;
final ButtonType type;
final Icon? icon;
TrustyButton({
super.key,
required this.onTap,
required this.text,
required this.type,
this.icon,
});
final Map<ButtonType, Map<String, Color>> color = {...}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => OrderService(),
child: Consumer<OrderService>(
builder: (context, orderService, _) => GestureDetector(
onTap: () {
onTap();
},
child: Opacity(
opacity: orderService.isLoading ? 0.5 : 1,
child: Container(
height: 56,
decoration: BoxDecoration(
color: color[type]!['backgroundColor']!,
borderRadius: const BorderRadius.all(
Radius.circular(20),
),
boxShadow: [
BoxShadow(
color: const Color(0x15000000),
blurRadius: 10,
spreadRadius: 0,
offset: Offset.fromDirection(2, 2),
),
],
),
child: Center(
child: orderService.isLoading
? const CircularProgressIndicator(
color: Colors.white,
)
: renderButtonContent(),
),
),
),
),
),
);
}
}
您面临这个问题,因为您正在
OrderService
内创建 TrustyButton
的新实例。相反,您必须抬起 ChangeNotifierProvider<TrustyButton>
,并通过 Consumer
内的 TrustyButton
使用它。
这是一个最小的例子:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: ChangeNotifierProvider(
create: (context) => OrderService(),
builder: (context, _) {
return TrustyButton(
onTap: () => context.read<OrderService>().deleteOrderWithId(),
);
},
),
),
),
);
}
}
class OrderService with ChangeNotifier {
bool _isLoading = false;
bool get isLoading => _isLoading;
void _toggleLoading() {
_isLoading = !_isLoading;
notifyListeners();
}
Future<void> deleteOrderWithId() async {
try {
_toggleLoading();
await Future.delayed(const Duration(seconds: 5));
} catch (err) {
print(err);
} finally {
_toggleLoading();
}
}
}
class TrustyButton extends StatelessWidget {
final void Function() onTap;
TrustyButton({
super.key,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return Consumer<OrderService>(
builder: (context, orderService, _) => GestureDetector(
onTap: onTap,
child: Opacity(
opacity: orderService.isLoading ? 0.5 : 1,
child: Container(
height: 56,
decoration: BoxDecoration(
color: Colors.amberAccent,
borderRadius: const BorderRadius.all(
Radius.circular(20),
),
boxShadow: [
BoxShadow(
color: const Color(0x15000000),
blurRadius: 10,
spreadRadius: 0,
offset: Offset.fromDirection(2, 2),
),
],
),
child: Center(
child: orderService.isLoading
? const CircularProgressIndicator(
color: Colors.white,
)
: Text('Delete'),
),
),
),
),
);
}
}