你好,我在理解如何在获取数据时使用提供程序方面遇到了很多困难。
假设我有一个http服务来获取数据并更新列表:
我的供应商.dart:
class InventoryProvider extends ChangeNotifier {
List<Item> _items = [];
List<Item> get items => List.unmodifiable(_items);
Future<List<Item>> fetchAllItems() async {
_items = await ItemService().fetchAllItems();
notifyListeners();
return items;
}
}
现在我想建立我的列表。我发现的唯一可行的解决方案是:
我的屏幕:
class InventoryScreen extends StatefulWidget {
static const routeName = '/';
const InventoryScreen({
super.key,
});
@override
State<InventoryScreen> createState() => _InventoryScreenState();
}
class _InventoryScreenState extends State<InventoryScreen> {
final List<Item> _items = [];
bool _isLoading = false;
String _errorMessage = '';
/// Fetch items
@override
void initState() {
super.initState();
_isLoading = true;
final itemProvider = Provider.of<InventoryProvider>(context, listen: false);
itemProvider.fetchAllItems().then((posts) {
setState(() {
for (Item item in posts) {
_items.add(item);
}
_isLoading = false;
});
}).catchError((e) {
setState(() {
_errorMessage = e.message;
_isLoading = false;
});
});
}
...
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
...
body: _isLoading
? const Center(child: CircularProgressIndicator())
: _errorMessage.isNotEmpty
? Center(child: Text(_errorMessage))
: _items.isEmpty
? const Center(child: Text('You do not have any item yet.'))
: ListView.builder(
itemCount: _items.length,
itemBuilder: (BuildContext context, int index) {
final item = _items[index];
return ListTile(
因此,这对于第一次获取的工作原理如下:
- 它在获取数据时显示一些东西(进度指示器)。
- 我从供应商那里获得所有数据。
它不适用于:
- 在提供程序发生更改时刷新列表(例如,如果在访问项目详细信息时可以删除列表中的一个项目,然后重新弹出到列表)。
我尝试过的:
- 移除
listen: False
。触发器:
Exception has occurred.
FlutterError (dependOnInheritedWidgetOfExactType<_InheritedProviderScope<InventoryProvider?>>() or dependOnInheritedElement() was called before _InventoryScreenState.initState() completed.
When an inherited widget changes, for example if the value of Theme.of() changes, its dependent widgets are rebuilt. If the dependent widget's reference to the inherited widget is in a constructor or an initState() method, then the rebuilt dependent widget will not reflect the changes in the inherited widget.
Typically references to inherited widgets should occur in widget build() methods. Alternatively, initialization based on inherited widgets can be placed in the didChangeDependencies method, which is called after initState and whenever the dependencies change thereafter.)
- 使用listen false将
initState
更改为didChangeDependencies
:进入请求的无限循环。
有没有人能帮你解决这个问题?
1条答案
按热度按时间2hh7jdfx1#
在您的ImageProvider中执行以下更改:
在您的initState中执行以下更改:
使用selector Package scaffold如下: