Flutter 从 API snapshot.hasError 获取数据
Flutter Fetch Data From API snapshot.hasError
现在我尝试从 pexels.com 张照片 api 中获取数据。我在上个月成功完成了这项工作。现在我更新了我的 flutter 版本并再次 运行 这段代码。但是现在这段代码出现了错误。
一直显示snapshot.hasError
我的包裹
import 'dart:convert';
import '../widgets/gridPhotos.dart';
import '../models/photoSearchModel.dart'; //used to decode json by https://app.quicktype.io
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
状态小部件
class WallpaperScreen extends StatefulWidget {
@override
_WallpaperScreenState createState() => _WallpaperScreenState();
}
class _WallpaperScreenState extends State<WallpaperScreen> {
int page = 1;
PhotoSearchModel jsonPhotoHTTPGet;
List<Photo> photos = List<Photo>();
ScrollController _scrollController = ScrollController();
@override
void initState() {
getWallpapers("wallpaper", page);
super.initState();
_sc.addListener(() {
if (_sc.position.pixels == _sc.position.maxScrollExtent) {
getWallpapers("wallpaper", page);
}
});
}
从 pexels 获取数据的函数 api
getCatergoryListWallpapers(int pageNo) async {
await http.get(
"https://api.pexels.com/v1/search?query=${widget.catergoryName}&per_page=50&page=${pageNo.toString()}",
headers: {
"Authorization":
"Auth Token" // Auth Token Works 100%
},
).then((value) {
jsonPhotoHTTPGet = photoSearchModelFromJson(value.body);
Map<String, dynamic> jsonData = jsonDecode(value.body);
jsonData["photos"].forEach((element) {
Photo photosModel = new Photo();
photosModel = Photo.fromJson(element);
photos.add(photosModel);
print(element);
});
setState(() {
page++;
});
});
return photos;
}
Future Builder 小部件
@override
Widget build(BuildContext context) {
return FutureBuilder<void>(
future: getCatergoryListWallpapers(page),
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
if (snapshot.hasData) {
return Container(
padding: EdgeInsets.all(8),
child: ListView.separated(
scrollDirection: Axis.horizontal,
controller: _scrollController,
separatorBuilder: (BuildContext context, int index) {
return SizedBox(
width: 10.0,
height: double.infinity,
);
},
itemCount: photos.length,
itemBuilder: (BuildContext context, int index) {
return Container(
// My Code Goes Here
);
},
),
);
} else if (snapshot.hasError) {
return Center(
child:Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
如果我运行这个代码这个return错误大纲图标
并且此代码来自 Future Builder elseif(snapshot.hasError){/* 图标代码 */}
Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
PhotoSearch.dart
// Using app.quicktype.io
import 'dart:convert';
PhotoSearchModel photoSearchModelFromJson(String str) =>
PhotoSearchModel.fromJson(json.decode(str));
String photoSearchModelToJson(PhotoSearchModel data) =>
json.encode(data.toJson());
class PhotoSearchModel {
PhotoSearchModel({
this.totalResults,
this.page,
this.perPage,
this.photos,
this.nextPage,
});
int totalResults;
int page;
int perPage;
List<Photo> photos;
String nextPage;
factory PhotoSearchModel.fromJson(Map<String, dynamic> json) =>
PhotoSearchModel(
totalResults: json["total_results"],
page: json["page"],
perPage: json["per_page"],
photos: List<Photo>.from(json["photos"].map((x) => Photo.fromJson(x))),
nextPage: json["next_page"],
);
Map<String, dynamic> toJson() => {
"total_results": totalResults,
"page": page,
"per_page": perPage,
"photos": List<dynamic>.from(photos.map((x) => x.toJson())),
"next_page": nextPage,
};
}
class Photo {
Photo({
this.id,
this.width,
this.height,
this.url,
this.photographer,
this.photographerUrl,
this.photographerId,
this.avgColor,
this.src,
this.liked,
});
int id;
int width;
int height;
String url;
String photographer;
String photographerUrl;
int photographerId;
String avgColor;
Src src;
bool liked;
factory Photo.fromJson(Map<String, dynamic> json) => Photo(
id: json["id"],
width: json["width"],
height: json["height"],
url: json["url"],
photographer: json["photographer"],
photographerUrl: json["photographer_url"],
photographerId: json["photographer_id"],
avgColor: json["avg_color"],
src: Src.fromJson(json["src"]),
liked: json["liked"],
);
Map<String, dynamic> toJson() => {
"id": id,
"width": width,
"height": height,
"url": url,
"photographer": photographer,
"photographer_url": photographerUrl,
"photographer_id": photographerId,
"avg_color": avgColor,
"src": src.toJson(),
"liked": liked,
};
}
class Src {
Src({
this.original,
this.large2X,
this.large,
this.medium,
this.small,
this.portrait,
this.landscape,
this.tiny,
});
String original;
String large2X;
String large;
String medium;
String small;
String portrait;
String landscape;
String tiny;
factory Src.fromJson(Map<String, dynamic> json) => Src(
original: json["original"],
large2X: json["large2x"],
large: json["large"],
medium: json["medium"],
small: json["small"],
portrait: json["portrait"],
landscape: json["landscape"],
tiny: json["tiny"],
);
Map<String, dynamic> toJson() => {
"original": original,
"large2x": large2X,
"large": large,
"medium": medium,
"small": small,
"portrait": portrait,
"landscape": landscape,
"tiny": tiny,
};
}
现在我的问题是为什么此代码在 flutter 升级 后不起作用?
并且总是 Return 快照错误。
在我的调试控制台中说
E/flutter (12657):
E/flutter (12657): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: NoSuchMethodError: The method 'forEach' was called on null.
E/flutter (12657): Receiver: null
E/flutter (12657): Tried calling: forEach(Closure: (dynamic) => Null)
E/flutter (12657): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
E/flutter (12657): #1 _WallpaperScreenState.getWallpapers (package:wallpaperworld/screens/wallpaperScreen.dart:39:24)
E/flutter (12657): <asynchronous suspension>
E/flutter (12657):
E/flutter (12657): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: NoSuchMethodError: The method 'map' was called on null.
E/flutter (12657): Receiver: null
E/flutter (12657): Tried calling: map(Closure: (dynamic) => Photo)
E/flutter (12657): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
E/flutter (12657): #1 new PhotoSearchModel.fromJson (package:wallpaperworld/models/photoSearch.dart:29:49)
E/flutter (12657): #2 photoSearchModelFromJson (package:wallpaperworld/models/photoSearch.dart:4:22)
E/flutter (12657): #3 _CategoryListViewBuilderState.getCatergoryListWallpapers.<anonymous closure> (package:wallpaperworld/widgets/categoryPhotos.dart:73:26)
E/flutter (12657): #4 _rootRunUnary (dart:async/zone.dart:1362:47)
E/flutter (12657): #5 _CustomZone.runUnary (dart:async/zone.dart:1265:19)
E/flutter (12657): #6 _FutureListener.handleValue (dart:async/future_impl.dart:152:18)
E/flutter (12657): #7 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:704:45)
E/flutter (12657): #8 Future._propagateToListeners (dart:async/future_impl.dart:733:32)
E/flutter (12657): #9 Future._completeWithValue (dart:async/future_impl.dart:539:5)
E/flutter (12657): #10 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:254:13)
E/flutter (12657): #11 _withClient (package:http/http.dart)
E/flutter (12657): <asynchronous suspension>
和
Another exception was thrown: 'package:flutter/src/widgets/basic.dart': Failed assertion: line 3709 pos 15: 'left == null || right == null || width == null': is not
true.
原因很可能是您的授权令牌已过期,它们的预期寿命有限(出于安全原因)。
这是我的猜测,如果您想了解更多详细信息,您应该打印错误。
你也可以尝试在hasError之前添加connectionState条件:
if (snapshot.connectionState == ConnectionState.active && snapshot.hasError)
好的。因此,我尝试使用您的密钥和所有内容访问 API,但出现以下错误:
{
"error": "Rate limit exceeded"
}
一个建议是不要在您的问题中这样提供您的密钥。二是修复API端的错误。这不是 Flutter 错误。
现在我尝试从 pexels.com 张照片 api 中获取数据。我在上个月成功完成了这项工作。现在我更新了我的 flutter 版本并再次 运行 这段代码。但是现在这段代码出现了错误。
一直显示snapshot.hasError
我的包裹
import 'dart:convert';
import '../widgets/gridPhotos.dart';
import '../models/photoSearchModel.dart'; //used to decode json by https://app.quicktype.io
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
状态小部件
class WallpaperScreen extends StatefulWidget {
@override
_WallpaperScreenState createState() => _WallpaperScreenState();
}
class _WallpaperScreenState extends State<WallpaperScreen> {
int page = 1;
PhotoSearchModel jsonPhotoHTTPGet;
List<Photo> photos = List<Photo>();
ScrollController _scrollController = ScrollController();
@override
void initState() {
getWallpapers("wallpaper", page);
super.initState();
_sc.addListener(() {
if (_sc.position.pixels == _sc.position.maxScrollExtent) {
getWallpapers("wallpaper", page);
}
});
}
从 pexels 获取数据的函数 api
getCatergoryListWallpapers(int pageNo) async {
await http.get(
"https://api.pexels.com/v1/search?query=${widget.catergoryName}&per_page=50&page=${pageNo.toString()}",
headers: {
"Authorization":
"Auth Token" // Auth Token Works 100%
},
).then((value) {
jsonPhotoHTTPGet = photoSearchModelFromJson(value.body);
Map<String, dynamic> jsonData = jsonDecode(value.body);
jsonData["photos"].forEach((element) {
Photo photosModel = new Photo();
photosModel = Photo.fromJson(element);
photos.add(photosModel);
print(element);
});
setState(() {
page++;
});
});
return photos;
}
Future Builder 小部件
@override
Widget build(BuildContext context) {
return FutureBuilder<void>(
future: getCatergoryListWallpapers(page),
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
if (snapshot.hasData) {
return Container(
padding: EdgeInsets.all(8),
child: ListView.separated(
scrollDirection: Axis.horizontal,
controller: _scrollController,
separatorBuilder: (BuildContext context, int index) {
return SizedBox(
width: 10.0,
height: double.infinity,
);
},
itemCount: photos.length,
itemBuilder: (BuildContext context, int index) {
return Container(
// My Code Goes Here
);
},
),
);
} else if (snapshot.hasError) {
return Center(
child:Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
如果我运行这个代码这个return错误大纲图标 并且此代码来自 Future Builder elseif(snapshot.hasError){/* 图标代码 */}
Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
PhotoSearch.dart
// Using app.quicktype.io
import 'dart:convert';
PhotoSearchModel photoSearchModelFromJson(String str) =>
PhotoSearchModel.fromJson(json.decode(str));
String photoSearchModelToJson(PhotoSearchModel data) =>
json.encode(data.toJson());
class PhotoSearchModel {
PhotoSearchModel({
this.totalResults,
this.page,
this.perPage,
this.photos,
this.nextPage,
});
int totalResults;
int page;
int perPage;
List<Photo> photos;
String nextPage;
factory PhotoSearchModel.fromJson(Map<String, dynamic> json) =>
PhotoSearchModel(
totalResults: json["total_results"],
page: json["page"],
perPage: json["per_page"],
photos: List<Photo>.from(json["photos"].map((x) => Photo.fromJson(x))),
nextPage: json["next_page"],
);
Map<String, dynamic> toJson() => {
"total_results": totalResults,
"page": page,
"per_page": perPage,
"photos": List<dynamic>.from(photos.map((x) => x.toJson())),
"next_page": nextPage,
};
}
class Photo {
Photo({
this.id,
this.width,
this.height,
this.url,
this.photographer,
this.photographerUrl,
this.photographerId,
this.avgColor,
this.src,
this.liked,
});
int id;
int width;
int height;
String url;
String photographer;
String photographerUrl;
int photographerId;
String avgColor;
Src src;
bool liked;
factory Photo.fromJson(Map<String, dynamic> json) => Photo(
id: json["id"],
width: json["width"],
height: json["height"],
url: json["url"],
photographer: json["photographer"],
photographerUrl: json["photographer_url"],
photographerId: json["photographer_id"],
avgColor: json["avg_color"],
src: Src.fromJson(json["src"]),
liked: json["liked"],
);
Map<String, dynamic> toJson() => {
"id": id,
"width": width,
"height": height,
"url": url,
"photographer": photographer,
"photographer_url": photographerUrl,
"photographer_id": photographerId,
"avg_color": avgColor,
"src": src.toJson(),
"liked": liked,
};
}
class Src {
Src({
this.original,
this.large2X,
this.large,
this.medium,
this.small,
this.portrait,
this.landscape,
this.tiny,
});
String original;
String large2X;
String large;
String medium;
String small;
String portrait;
String landscape;
String tiny;
factory Src.fromJson(Map<String, dynamic> json) => Src(
original: json["original"],
large2X: json["large2x"],
large: json["large"],
medium: json["medium"],
small: json["small"],
portrait: json["portrait"],
landscape: json["landscape"],
tiny: json["tiny"],
);
Map<String, dynamic> toJson() => {
"original": original,
"large2x": large2X,
"large": large,
"medium": medium,
"small": small,
"portrait": portrait,
"landscape": landscape,
"tiny": tiny,
};
}
现在我的问题是为什么此代码在 flutter 升级 后不起作用?
并且总是 Return 快照错误。
在我的调试控制台中说
E/flutter (12657):
E/flutter (12657): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: NoSuchMethodError: The method 'forEach' was called on null.
E/flutter (12657): Receiver: null
E/flutter (12657): Tried calling: forEach(Closure: (dynamic) => Null)
E/flutter (12657): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
E/flutter (12657): #1 _WallpaperScreenState.getWallpapers (package:wallpaperworld/screens/wallpaperScreen.dart:39:24)
E/flutter (12657): <asynchronous suspension>
E/flutter (12657):
E/flutter (12657): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: NoSuchMethodError: The method 'map' was called on null.
E/flutter (12657): Receiver: null
E/flutter (12657): Tried calling: map(Closure: (dynamic) => Photo)
E/flutter (12657): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
E/flutter (12657): #1 new PhotoSearchModel.fromJson (package:wallpaperworld/models/photoSearch.dart:29:49)
E/flutter (12657): #2 photoSearchModelFromJson (package:wallpaperworld/models/photoSearch.dart:4:22)
E/flutter (12657): #3 _CategoryListViewBuilderState.getCatergoryListWallpapers.<anonymous closure> (package:wallpaperworld/widgets/categoryPhotos.dart:73:26)
E/flutter (12657): #4 _rootRunUnary (dart:async/zone.dart:1362:47)
E/flutter (12657): #5 _CustomZone.runUnary (dart:async/zone.dart:1265:19)
E/flutter (12657): #6 _FutureListener.handleValue (dart:async/future_impl.dart:152:18)
E/flutter (12657): #7 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:704:45)
E/flutter (12657): #8 Future._propagateToListeners (dart:async/future_impl.dart:733:32)
E/flutter (12657): #9 Future._completeWithValue (dart:async/future_impl.dart:539:5)
E/flutter (12657): #10 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:254:13)
E/flutter (12657): #11 _withClient (package:http/http.dart)
E/flutter (12657): <asynchronous suspension>
和
Another exception was thrown: 'package:flutter/src/widgets/basic.dart': Failed assertion: line 3709 pos 15: 'left == null || right == null || width == null': is not
true.
原因很可能是您的授权令牌已过期,它们的预期寿命有限(出于安全原因)。
这是我的猜测,如果您想了解更多详细信息,您应该打印错误。
你也可以尝试在hasError之前添加connectionState条件:
if (snapshot.connectionState == ConnectionState.active && snapshot.hasError)
好的。因此,我尝试使用您的密钥和所有内容访问 API,但出现以下错误:
{
"error": "Rate limit exceeded"
}
一个建议是不要在您的问题中这样提供您的密钥。二是修复API端的错误。这不是 Flutter 错误。