问题:我正在尝试构建一个从 JSON 文件获取数据的小部件,但我不确定为什么提供程序不更新该小部件。 (调试时没有错误,只是小部件没有更新。)
这是应该显示 JSON 数据的小部件。
class CatalogPage extends StatefulWidget {
@override
_CatalogPageState createState() => _CatalogPageState();
}
class _CatalogPageState extends State<CatalogPage>
with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true; // needed for keepAlive
@override
Widget build(BuildContext context) {
super.build(context); // needed for keepAlive
bool _loading = Provider.of<Screen1Provider>(context, listen: true).getLoading;
List _catalogItems =
Provider.of<Screen1Provider>(context, listen: false).getCatalogItems;
return Scaffold(
body: _loading == true
? Center(
child: CircularProgressIndicator(),
)
: ListView.builder(
itemCount: _catalogItems.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text(_catalogItems[index].code.toString()),
),
);
},
));
}
@override
void initState() {
print('hi from catalogPage!');
Screen1Provider().updateJsonCatalog();
super.initState();
}
}
这是上述小部件的提供者数据
class Screen1Provider with ChangeNotifier {
int _catalogPageIndex = 1;
int _medidasPageIndex = 0;
List _itemsCatalog = [];
List _itemsMedidas = [];
List _itemsExcluded = [];
bool _loading = true;
int get getCatalogPageIndex => _catalogPageIndex;
bool get getLoading => _loading;
void setLoading(bool boolean) {
_loading = boolean;
notifyListeners();
}
void setCatalogPageIndex(int index) {
_catalogPageIndex = index;
notifyListeners();
}
void setItemsCatalog(data) {
_itemsCatalog = data;
print('> setItemsCatalog');
print(_itemsCatalog[0].code); //printing correctly here as well
getItemsCatalog;
}
List get getItemsCatalog {
print('> getItemsCatalog');
if (_itemsCatalog.length > 0) {
print(_itemsCatalog[0].desc); //printing correctly here as well
}
return _itemsCatalog;
}
void setItemsMedidasGroup(data) {
// _itemsMedidas.addAll(data);
// _itemsMedidas = data;
}
void setItemsExcluded(data) {
// _itemsExcluded.addAll(data);
// _itemsExcluded = data;
}
void updateJsonCatalog() {
print('updating catalog');
setLoading(true);
_itemsCatalog.clear();
_itemsMedidas.clear();
_itemsExcluded.clear();
getJsonCatalog().then((data) {
setItemsCatalog(data[0]);
// setItemsMedidasGroup(data[1]);
// setItemsExcluded(data[2]);
setLoading(false);
print('> is loading?: $_loading');
});
}
// Function to get catalog in json
Future<List> getJsonCatalog() async {
print('trying to download catalog...');
List _returnList = [];
String _url =
'https://www.dropbox.com/s/qubo8rigrkkvnqm/DummyJsonTest.json?dl=1';
try {
var r = await http.get(_url);
var jsonData = json.decode(r.body);
// this is used to prevent Price error when it's empty
// messes up with double.parse formulas
String tempPrice;
for (var header in jsonData) {
if (header["CODIGO"] == '') {
// skip if empty
continue;
}
if (header["PRECIO"] == '') {
tempPrice = '0.00';
} else {
tempPrice = header["PRECIO"];
}
CatalogItems item = CatalogItems(
header["CODIGO"],
header["DESCRIPCION"],
header["INVENT"],
double.parse(tempPrice).toStringAsFixed(2).toString(),
header["COD.ALT."],
header["DESC.ALT."],
header["GRUPO"],
(double.parse(tempPrice) * 0.8).toStringAsFixed(2).toString(),
);
// only add if item in CatalogItems.groups
if (CatalogItems.groups.contains(header["GRUPO"])) {
_itemsCatalog.add(item);
} else if (CatalogItems.medidaGroups.contains(header["GRUPO"])) {
_itemsMedidas.add(item);
} else {
_itemsExcluded.add(item);
}
}
} catch (e) {
print('error');
print(e);
} finally {
// this triggers even if catalog failed to download
}
// below will NOT trigger if an error was catched
print('no errors while downloading JSON');
print('${_itemsCatalog[0].code}|${_itemsCatalog[0].desc}|${_itemsCatalog[0].price}'); // prints correctly here
_returnList = [_itemsCatalog, _itemsMedidas, _itemsExcluded];
return _returnList;
}
}
请告诉我是否有更好的方法来做到这一点,因为我刚刚了解该提供商。
编辑:项目链接[ https://www.dropbox.com/sh/k8v8d730p0qmbvl/AABG1jcPC_Zpu7O2yLk_idmxa?dl=0][1]如果有错误,请注释掉 pubspec.yaml 文件中的资源。
EDIT2:向项目添加了虚拟 json 数据链接,因此请随意运行它。否则这是 json 数据:
[{"CODIGO": "13271190", "DESCRIPCION": "A/A CHE TRAX 13- GITY 2014-
SONI 13396514 95152912 52420930 CUK2", "INVENT": "890", "PRECIO": "3.54", "COD.ALT.": "AC9205", "DESC.ALT.": "", "GRUPO": "10.FILTRO A/A"}, {"CODIGO": "27274-7J125 SET", "DESCRIPCION": "A/A NIS PATHFINDER NEW 2015 - 2PC 27275-1N605", "INVENT": "637", "PRECIO": "4.42", "COD.ALT.": "AC2503 SET", "DESC.ALT.": "", "GRUPO": "10.FILTRO A/A"}, {"CODIGO": "27274-EA000 SET", "DESCRIPCION": "A/A NIS FRONTIER VQ40 YD25 PATHFIADER D40 VITARRA J20 27274-EL00A 27277-4JA0A", "INVENT": "1072", "PRECIO": "4.25", "COD.ALT.": "AC2507SET", "DESC.ALT.": "27277-4JA0A GRAN VITARRA J20", "GRUPO": "10.FILTRO A/A"}, {"CODIGO": "27274-EB700-F SET", "DESCRIPCION": "A/A NIS NAVARA D40T DELGADA 2 PCS CA18320", "INVENT": "1117", "PRECIO": "4.22", "COD.ALT.": "AC22005 SET", "DESC.ALT.": "", "GRUPO": "10.FILTRO A/A"}, {"CODIGO": "27275-1N601", "DESCRIPCION": "A/A NIS FRONTIER VQ25D -02 QG 16 ZD30 QD32", "INVENT": "314", "PRECIO": "4.95", "COD.ALT.": "AC2502SET", "DESC.ALT.": "", "GRUPO": "10.FILTRO A/A"}, {"CODIGO": "27277-00A26", "DESCRIPCION": "A/A NIS TIIDA C13 HR16 15- JUKE 2015- HR16DE VERSA 27277-1KA0A", "INVENT": "2061", "PRECIO": "3.65", "COD.ALT.": "AC0182", "DESC.ALT.": "", "GRUPO": "10.FILTRO A/A"}, {"CODIGO": "27277-1HA0A", "DESCRIPCION": "A/A NIS QASHQAI 13- VERSA 14- MARCH 13- ALMERA 11- K1267 27277-4BA0A", "INVENT": "1777", "PRECIO": "3.82", "COD.ALT.": "AC2513", "DESC.ALT.": "", "GRUPO": "10.FILTRO A/A"}, {"CODIGO": "27277-1KK0A", "DESCRIPCION": "A/A NIS VERSA 2015- HOT", "INVENT": "2642", "PRECIO": "4.95", "COD.ALT.": "", "DESC.ALT.": "", "GRUPO": "10.FILTRO A/A"}, {"CODIGO": "27277-3JC1B", "DESCRIPCION": "A/A NI MURANO 14- PATHFINDER 2013- QR25D ALTIMA 12-", "INVENT": "451", "PRECIO": "4.65", "COD.ALT.": "AC0208", "DESC.ALT.": "", "GRUPO": "10.FILTRO A/A"}, {"CODIGO": "27277-4BA0A", "DESCRIPCION": "A/A NIS XTRAIL 13- RENAULT CA18361 27277-1HA0A", "INVENT": "426", "PRECIO": "3.71", "COD.ALT.": "A2514", "DESC.ALT.": "", "GRUPO": "10.FILTRO A/A"}, {"CODIGO": "27277-4KH0A", "DESCRIPCION": "A/A NI URBAN NV350 12- PASTROL 10- PATHFHANER 16- OF", "INVENT": "1420", "PRECIO": "3.89", "COD.ALT.": "27277-5JJ0A", "DESC.ALT.": "", "GRUPO": "10.FILTRO A/A"}]
Edit3:改进了调试打印,验证了 bool 触发器是否正确。但小部件仍然没有更新(CircularProgressIndicator() 应该只显示 bool 值是否为 false,但它会永远旋转)
I/flutter ( 5948): hi from catalogPage!
I/flutter ( 5948): updating catalog
I/flutter ( 5948): trying to download catalog...
I/flutter ( 5948): > getItemsCatalog
I/flutter ( 5948): no errors, done
I/flutter ( 5948): 13271190|A/A CHE TRAX 13- GITY 2014- SONI 13396514 95152912 52420930 CUK2|3.54
I/flutter ( 5948): > setItemsCatalog
I/flutter ( 5948): 13271190
I/flutter ( 5948): > getItemsCatalog
I/flutter ( 5948): A/A CHE TRAX 13- GITY 2014- SONI 13396514 95152912 52420930 CUK2
I/flutter ( 5948): > is loading?: false
最佳答案
错误出现在 CatalogPage() 类中的这段代码中:
void initState() {
print('hi from catalogPage!');
Screen1Provider().updateJsonCatalog(); // <----- The culprit
super.initState();
}
我发现它的方法是向 Screen1Provider 添加一个构造函数,如下所示:
Screen1Provider(){
print("***started provider***");
}
我注意到该行被打印了两次......并且提供者仅在第一次使用后实例化一次。
当您调用 Screen1Provider().updateJsonCatalog() 时,它在 main.dart 文件中的 ChangeNotifierProvider() 之外创建了一个 ScreenProvider 的新实例。这就是破坏notifyListeners调用的原因。为了调用代码,您需要运行:
Provider.of<Screen1Provider>(context, listen: false).updateJsonCatalog();
之后,代码运行得很好......好吧......仍然有一些机会,但我能够看到这一点:
哇。这真是一个微妙的错误! (我还通过查看您的代码学到了一些东西......所以它一直都是双赢!
关于即使我测试了数据是否正确,Flutter Provider 也没有更新我的 Widget?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60368340/