#java #flutter #future #flutter-futurebuilder
#java #флаттер #будущее #flutter-futurebuilder
Вопрос:
Я новичок в flutter и имею опыт работы только с PHP, поэтому вы можете счесть мои вопросы бессмысленными. Если да, пожалуйста, объясните мне, в чем я ошибаюсь, спасибо. Я использую два проекта в качестве источника для своего проекта: https://github.com/abdl-slm/FlutterGridFutureExample и https://github.com/PoojaB26/ParsingJSON-Flutter .
Я пытаюсь изменить данные get из API с помощью Future builder и grid_view, но я получаю это сообщение, когда пытаюсь вернуть список из future:
Значение типа ‘ActionsList’ не может быть возвращено из функции ‘getActions’, поскольку оно имеет возвращаемый тип ‘Future<Список>’.
Я проверил, что нет проблем с анализом данных в ActionsList (я могу распечатать их внутри future), но я не могу передать их остальной части futurebuilder.
Будущее выглядит следующим образом:
Future<List<ActionsList>> getActions() async {
final response = await http.get(
"https://www.myproject.cz/api/...",
headers: {
"contentType": "application/x-www-form-urlencoded",
"Authorization": "Bearer ...",
},
);
if (response.statusCode == 200) {
Map<String, dynamic> decodedActions = json.decode(response.body);
String encodedActions = jsonEncode(decodedActions['actions_data']);
final jsonResponse = json.decode(encodedActions);
ActionsList actionsList = ActionsList.fromJson(jsonResponse);
print("got data from API check: " actionsList.actions[0].name);
return actionsList;
} else {
throw Exception('Failed to load actions');
}
}
JSON из API:
{
"actions_data": [
{
"id": "245629634987701888",
"shop_id": "182980954485185472",
"name": "Slevový kupón 10 % na techniku na FotoŠkoda",
"valid_from": "2020-11-08T00:00:00 00:00",
"valid_to": null,
"description": "",
"type": "coupon",
"other_type": null,
"discount": "10",
"discount_type": "%",
"discount_coupon": "POH10",
"image_mobile_url": null,
"aggregator": "affiliate_port",
"redirect_link": "https://project.cz/aff_c?offer_id=234amp;aff_id=5921amp;aff_sub=107553508877665280"
},
{
"id": "245628934350208704",
"shop_id": "180719630782866560",
"name": "Slevový kupon 200 Kč na dioptrické brýle na Alensa",
"valid_from": "2020-11-08T00:00:00 00:00",
"valid_to": null,
"description": "",
"type": "coupon",
"other_type": null,
"discount": "200",
"discount_type": "CZK",
"discount_coupon": "dioptricke200",
"image_mobile_url": null,
"aggregator": "ehub",
"redirect_link": "https://project.cz/click.php?a_aid=bb9f4d85amp;a_bid=acf4b661amp;data1=107553508877665280"
},
{
"id": "243716688296602880",
"shop_id": "194864134897055232",
"name": "Sleva na nábytek až 20%",
"valid_from": "2020-11-03T00:00:00 00:00",
"valid_to": null,
"description": "",
"type": "coupon",
"other_type": null,
"discount": "10",
"discount_type": "%",
"discount_coupon": "20AUTUMN",
"image_mobile_url": "https://www.project.cz/actions-images/243716688296602880-mobile-699018679.png",
"aggregator": "dognet",
"redirect_link": "http://www.project.cz/sd?data1=107553508877665280"
},...
Класс ActionList для сопоставления данных:
import 'dart:convert';
class ActionsList {
final List<ActionsData> actions;
ActionsList({
this.actions,
});
factory ActionsList.fromJson(List<dynamic> parsedJson) {
List<ActionsData> actions = new List<ActionsData>();
actions = parsedJson.map((i)=>ActionsData.fromJson(i)).toList();
return new ActionsList(
actions: actions
);
}
}
class ActionsData {
final String id;
final String shopId;
final String name;
final String validFrom;
final String validTo;
final String description;
final String type;
final String otherType;
final String discount;
final String discountType;
final String discountCoupon;
final String imageMobileUrl;
final String aggregator;
final String redirectLink;
ActionsData(
{this.id,
this.shopId,
this.name,
this.validFrom,
this.validTo,
this.description,
this.type,
this.otherType,
this.discount,
this.discountType,
this.discountCoupon,
this.imageMobileUrl,
this.aggregator,
this.redirectLink});
Map<String, dynamic> toJson(){
return {
"id": this.id,
"shopId": this.shopId,
"name": this.name,
"validFrom": this.validFrom,
"validTo": this.validTo,
"description": this.description,
"type": this.type,
"otherType": this.otherType,
"discount": this.discount,
"discountType": this.discountType,
"discountCoupon": this.discountCoupon,
"imageMobileUrl": this.imageMobileUrl,
"aggregator": this.aggregator,
"redirectLink": this.redirectLink
};
}
factory ActionsData.fromJson(Map<String, dynamic> json){
return new ActionsData(
id: json['id'],
shopId: json['shop_id'],
name: json['name'],
validFrom: json['valid_from'],
validTo: json['valid_to'],
description: json['description'],
type: json['type'],
otherType: json['other_type'],
discount: json['discount'],
discountType: json['discount_type'],
discountCoupon: json['discount_coupon'],
imageMobileUrl: json['image_mobile_url'],
aggregator: json['aggregator'],
redirectLink: json['redirect_link']);
}
}
И остальная часть главного экрана:
class ThirdScreen extends StatefulWidget {
ThirdScreen({Key key, this.title}) : super(key: key);
final String title;
@override
_ThirdScreenState createState() => _ThirdScreenState();
}
class _ThirdScreenState extends State<ThirdScreen> with TickerProviderStateMixin {
Future<List<ActionsList>> futureAction;
@override
void initState() {
super.initState();
futureAction = getActions();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
titleSpacing: 0.0,
title: IconButton(
icon: Icon(
Icons.shopping_cart,
),
onPressed: () {},
),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.menu,
),
onPressed: () {},
)
],
),
body: Center(
child: FutureBuilder<List<ActionsList>>(
future: futureAction,
builder: (context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
print("snapshot doesn't have data");
return Center(child: CircularProgressIndicator());
} else {
// print(snapshot.data);
return Container(child: _albumGridView(snapshot.data));
}
},
)),
);
}
}
Спасибо за любые подсказки или примеры!
Ответ №1:
ваш метод Future ничего не вернет, если вы не вернете значение вне оператора else if . измените свой код на:
Future<List<ActionsList>> getActions() async {
ActionsList actionsList;
final response = await http.get(
"https://www.myproject.cz/api/...",
headers: {
"contentType": "application/x-www-form-urlencoded",
"Authorization": "Bearer ...",
},
);
if (response.statusCode == 200) {
Map<String, dynamic> decodedActions = json.decode(response.body);
String encodedActions = jsonEncode(decodedActions['actions_data']);
final jsonResponse = json.decode(encodedActions);
actionsList = ActionsList.fromJson(jsonResponse);
print("got data from API check: " actionsList.actions[0].name);
} else {
throw Exception('Failed to load actions');
}
return actionsList;
}
надеюсь, это сработает для вас.
Комментарии:
1. Спасибо, но проблема в другом — согласно Android Studio, я не использую правильный тип списка действий.. смотрите: ctrlv.cz/VQgf
Ответ №2:
Future<ActionsList>() async {
final response = await http.get(
"https://www.myproject.cz/api/...",
headers: {
"contentType": "application/x-www-form-urlencoded",
"Authorization": "Bearer ...",
},
);
if (response.statusCode == 200) {
Map<String, dynamic> decodedActions = json.decode(response.body);
String encodedActions = jsonEncode(decodedActions['actions_data']);
final jsonResponse = json.decode(encodedActions);
ActionsList actionsList = ActionsList.fromJson(jsonResponse);
print("got data from API check: " actionsList.actions[0].name);
return actionsList;
} else {
throw Exception('Failed to load actions');
}
}
измените возвращаемый тип вашей функции с «Future<Список<Список действий>>» на «Future<Список действий>», и это решит вашу проблему.
Комментарии:
1. Привет, Захид, спасибо за вашу попытку, но при возврате списка действий все еще наблюдается несоответствие типов. Я думаю, что проблема в том, что JSON не прост, и мне нужно разобрать его по шагам … первый уровень как ActionList, а второй как ActionData … и я не уверен, как это сделать, используя future…