Я пытаюсь получить данные из своей модели, но я не получаю данные в текстовом виджете. После получения данных из JSON я использую модель для сохранения данных. Я могу распечатать данные после вызова API в функции, но не когда я пытался получить данные из модели внутри виджета. Я использую provider, но получаю нулевое значение от модели. Я не понимаю, как именно выполнить эту задачу, следуя моему объекту JSON.
{
"statusCode": 200,
"success": true,
"messages": [],
"data": [
{
"id": 36,
"title": "Muhurtam",
"filename": "Muhurtam.jpg",
"mimetype": "image/jpeg",
"directcalling": 1,
"parentid": null,
"subcat": [
{
"id": 50,
"title": "abc",
"filename": "abc.png",
"mimetype": "image/png",
"directcalling": 0,
"parentid": 36,
"subcat": []
}
]
Я создал класс модели для приведенного выше json, ниже моя модель
Модель
import 'package:flutter/material.dart';
class Categories with ChangeNotifier {
Categories({
this.statusCode,
this.success,
this.messages,
this.data,
});
late final int? statusCode;
late final bool? success;
late final List<dynamic>? messages;
late final List<Data>? data;
Categories.fromJson(Map<String, dynamic> json) {
statusCode = json['statusCode'];
success = json['success'];
messages = List.castFrom<dynamic, dynamic>(json['messages']);
data = List.from(json['data']).map((e) => Data.fromJson(e)).toList();
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
_data['statusCode'] = statusCode;
_data['success'] = success;
_data['messages'] = messages;
_data['data'] = data!.map((e) => e.toJson()).toList();
return _data;
}
List get items {
// if (_showFavoritesOnly) {
// return _items.where((prodItem) => prodItem.isFavorite).toList();
// }
return [...data!];
}
}
class Data extends ChangeNotifier {
Data({
this.id,
this.title,
this.filename,
this.mimetype,
this.directcalling,
this.parentid,
this.subcat,
});
late final int? id;
late final String? title;
late final String? filename;
late final String? mimetype;
late final int? directcalling;
late final Null parentid;
late final List<Subcat>? subcat;
Data.fromJson(Map<String, dynamic> json) {
id = json['id'];
title = json['title'];
filename = json['filename'];
mimetype = json['mimetype'];
directcalling = json['directcalling'];
parentid = null;
subcat = List.from(json['subcat']).map((e) => Subcat.fromJson(e)).toList();
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
// _data['id'] = id;
_data['title'] = title;
_data['filename'] = filename;
// _data['mimetype'] = mimetype;
_data['directcalling'] = directcalling;
// _data['parentid'] = parentid;
// _data['subcat'] = subcat.map((e) => e.toJson()).toList();
return _data;
}
}
class Subcat {
Subcat({
required this.id,
required this.title,
required this.filename,
required this.mimetype,
required this.directcalling,
required this.parentid,
required this.subcat,
});
late final int id;
late final String title;
late final String filename;
late final String mimetype;
late final int directcalling;
late final int parentid;
late final List<dynamic> subcat;
Subcat.fromJson(Map<String, dynamic> json) {
id = json['id'];
title = json['title'];
filename = json['filename'];
mimetype = json['mimetype'];
directcalling = json['directcalling'];
parentid = json['parentid'];
subcat = List.castFrom<dynamic, dynamic>(json['subcat']);
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
//_data['id'] = id;
_data['title'] = title;
_data['filename'] = filename;
//_data['mimetype'] = mimetype;
_data['directcalling'] = directcalling;
//_data['parentid'] = parentid;
//_data['subcat'] = subcat;
return _data;
}
}
Ниже приведен мой виджет, в котором я хочу проверить данные внутри моей модели. Я не понимаю, как именно вызывать данные, которые находятся внутри модели.
Widget build(BuildContext context) {
var image = Provider.of<FlutterFunctions>(context, listen: false);
var cat = Provider.of<Category>(context, listen: false).categories;
return Scaffold(
appBar: AppBar(),
drawer: const AppDrawer(),
body: Text("${cat?.data == null ? "there is no data" : cat!.statusCode}")
Преобразование API
class Category with ChangeNotifier {
Categories? categories;
Future<void> getCatogories(BuildContext cont) async {
final url = PurohitApi().baseUrl + PurohitApi().getcategory;
try {
final client = RetryClient(
http.Client(),
retries: 4,
when: (response) {
return response.statusCode == 401 ? true : false;
},
onRetry: (req, res, retryCount) async {
//print('retry started $token');
if (retryCount == 0 && res?.statusCode == 401) {
var accessToken = await Provider.of<Auth>(cont, listen: false)
.restoreAccessToken();
// Only this block can run (once) until done
req.headers['Authorization'] = accessToken;
}
},
);
var response = await client.get(
Uri.parse(url),
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
);
Map<String, dynamic> categoryTypes = json.decode(response.body);
categories = Categories.fromJson(categoryTypes);
notifyListeners();
} catch (e) {
print(e);
}
}
}
да, я уже преобразовал его, но я хочу использовать преобразованные данные внутри виджетов
Если вы сделали преобразование модели правильно, то я подозреваю ту часть, где вы это называете. Можете ли вы обновить свой вопрос с помощью кода, в котором вы вызываете преобразование из json (после ответа API).
обновление с преобразованием. Я Абель для печати данных из функции, в которой я вызываю API, но не получаю данные внутри виджетов.
Вы нигде не назначаете конвертированные категории. Должно быть что-то вроде: yourCategoriesInProvider = Categories.fromJson(categoryTypes);
Я обновил вопрос, который пробовал, как вы сказали, но не работал





Вы используете Provider неправильно. Ваши модели, такие как Categories, Data и т. д., не должны расширять ChangeNotifier. Вы должны создать класс Provider, который использует ChangeNotifier, который будет иметь данные вашей модели и предоставить их где-нибудь, чтобы использовать их с Provider.of<ProviderName>(context, listen: false). Что-то вроде этого:
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (ctx) => CategoriesProvider(),
child: MaterialApp(
home: Sample(),
),
);
}
}
class CategoriesProvider with ChangeNotifier {
Categories? categories;
Future<void> getCatogories() async {
Map<String, dynamic> categoryTypes = {
"statusCode": 200,
"success": true,
"messages": [],
"data": [
{
"id": 36,
"title": "Muhurtam",
"filename": "Muhurtam.jpg",
"mimetype": "image/jpeg",
"directcalling": 1,
"parentid": null,
"subcat": [
{
"id": 50,
"title": "abc",
"filename": "abc.png",
"mimetype": "image/png",
"directcalling": 0,
"parentid": 36,
"subcat": []
}
]
}
]
};
categories = Categories.fromJson(categoryTypes);
notifyListeners();
}
}
class Sample extends StatefulWidget {
const Sample({Key? key}) : super(key: key);
@override
State<Sample> createState() => _SampleState();
}
class _SampleState extends State<Sample> {
@override
void initState() {
Provider.of<CategoriesProvider>(context, listen: false).getCatogories();
super.initState();
}
@override
Widget build(BuildContext context) {
var cat = Provider.of<CategoriesProvider>(context, listen: false).categories;
return Scaffold(
appBar: AppBar(),
drawer: const Drawer(),
body: Text("${cat?.data == null ? "there is no data" : cat!.statusCode}"),
);
}
}
Я обновил вопрос, как вы сказали, я использовал свою модель в переменной, затем я назначаю свое преобразование модели и пытался вызвать данные, используя следующий код, но я не получил никаких данных cat.categories!.statusCode
Следуйте моему ответу и создайте свой Provider, как я сделал с CategoriesProvider. Предоставьте его вашему дереву виджетов с помощью ChangeNotifierProvider( create: (ctx) => CategoriesProvider(), child: MaterialApp( home: Sample(), ), и используйте его, как я сделал с var cat = Provider.of<CategoriesProvider>(context, listen: false).categories;, чтобы получить ваши категории в переменной и использовать ее дальше в дереве виджетов.
Я отредактировал свой вопрос, и код попробовал то, что вы сказали, создав провайдера, как вы сказали, в классе категории, вы можете проверить мой код преобразования API в вопросе, и я вызываю категории из преобразования API в моем виджете, но он не работает
Есть ошибки? Я не знаю, в чем сейчас ваша проблема, но мой ответ работает отлично, вы можете проверить его и увидеть, а затем настроить под свои нужды.
хм, в вашем коде есть проблема, но я не понимаю, почему он не работает
это сработало, спасибо, я только что удалил уведомление об изменении из модели
Да, как я сказал в ответ. Рад, что это сработало, удачного кодирования 😉
Вы можете использовать один из этих сайтов для анализа вашего кода
jsonвDart: javiercbk.github.io/json_to_dart или app.quicktype.io. Или вы можете использовать расширениеVisual Studio Codeпод названиемJson to Dart Modelдля той же цели.