I am trying to use the response.body from a request made in network.dart in main.dart, but it does not seem to work here is my code
import 'package:http/http.dart'as http;
import 'dart:async';
import 'dart:convert';
import 'dart:io';
class Network {
var data;
Future fetchData() async {
Map<String, String> headers = {
HttpHeaders.contentTypeHeader: "application/json",
HttpHeaders.acceptHeader: "application/json",
HttpHeaders.authorizationHeader: "Bearer $token",
};
http.Response response = await http.get (url),
headers: headers,
);
if (response.statusCode == 200) {
data = response.body;
return jsonDecode(data);
} else {
print('this is the ${response.statusCode}');
}
}
}
in the main.dart i am trying to print network.data but its null and when mapping json values i get all nulls what am i missing
Edit below i am assigning a var called body to to the result of the fetchdata in hte network but it does not seem to work when i print i run i get this "Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Future'"
import 'package:flutter/material.dart';
import 'package:foodicsclimamethod/networking.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Network network = Network();
String productName;
int productPrice;
String productData;
void updateUi() async {
Future<dynamic> body = await network.fetchData();
print(body);
}
#override
void initState() {
super.initState();
network.fetchData();
}
It looks like there is an issue with the updateUi method in your code sample. The body variable is typed as Future<dynamic>, however it should be dynamic because you are awaiting the fetchData method. If you wanted to, you could avoid specifying a type altogether and simply use final in order to infer the type. I have included a complete example below showing how this could all fit together:
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(MyApp());
}
class Network {
Future fetchData() async {
final headers = <String, String>{
HttpHeaders.contentTypeHeader: 'application/json',
HttpHeaders.acceptHeader: 'application/json',
HttpHeaders.authorizationHeader: 'Bearer $token',
};
final response = await http.get(url, headers: headers);
if (response.statusCode >= 200 && response.statusCode < 300) {
return json.decode(response.body);
} else {
throw Error();
}
}
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Future _future;
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _future,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Text(snapshot.data.toString());
} else {
return CircularProgressIndicator();
}
},
),
);
}
#override
void initState() {
super.initState();
_future = Network().fetchData();
}
}
Related
I am using http and trying to display the data and an error shows to me in the screen instead of the data I defined all the variables with the null safety he should print the data inside the title not the error
this is the json class #link#
this is the code
// ignore_for_file: unused_local_variable, avoid_print
import 'dart:convert';
import 'package:appii/models/post.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: Home(),
);
}
}
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
late Future<Post>
postdata; // this one is for saving the data in variable that i can use it anywhere
//we did the init state to allow the compile to print the data
#override
void initState() {
super.initState();
postdata = getPostById();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Networking http lesson 1'),
),
body: Center(
child: FutureBuilder<Post>(
future: postdata, // the data source
// in the builder i am going to desigm the place where the data will be in and it take #1- Context 2- snapshot#
builder: (context, snapshot) {
// this one is to see if there is data or eror
if (snapshot.hasData) {
return Text(snapshot.data!.title);
} else if (snapshot.hasError) {
return Text('error is ${snapshot.error}');
}
return const CircularProgressIndicator();
},
),
),
);
}
// this is the fuction that by it iam requesting to use the http package #http.# this is an object from the package i called containes all the methods inside this package
Future<Post> getPostById() async {
http.Response futurepost = await http.get(
Uri.parse(
'https://jsonplaceholder.typicode.com/posts/1'), // here in http.get or http.post first yu have to put ur url in the shape of #Uri.parse# To improve compile-time type safety
);
//this method #if# like .then but here i making sure that tha api and the link is working
if (futurepost.statusCode == 200) {
// success
print(futurepost.body);
return Post.fromjson(json.decode(futurepost
.body)); // in thie retuen iam taking the data and convert it form data with double qoutations to json
} else {
throw Exception(
'can not load data'); // here iam catching the error if there is one
}
}
}
here is the json i did with the constructor and named constructor
// this is the custom Response object
class Post {
late int userId;
late int id;
late String title;
late String body;
// normal Constructor
Post({
required this.userId,
required this.id,
required this.title,
required this.body,
});
//named Constructor
//factory is meaning that i do not want to create a new object every time but to use escesting one
factory Post.fromjson(Map<String, dynamic> jason) {
return Post(
id: jason['id'],
userId: jason['UserId'],
title: jason['title'],
body: jason['body'],
);
}
}
I like how you call json as jason makes it more personal, moreover the issue is most probably due to a typo here userId: jason['UserId'] because your screenshot shows it as userId: jason['userId'].
I want to draw a line chart catching the data from a JSON file. The JSON is inside the assets folder. But I do not know How to Develop a Line Chart using my JSON Data. Can please somebody help and guide me. Thank you very much.
Here is the JSON
{
"measure": [
{
"count": 8,
"range_array": [20.6, 27.9, 50.6],
"force_array": [116.8, 187.4, 226.6]
}
]
}
Here is the Model
class DataModel {
DataModel({this.measure});
List<DataTitle>? measure;
factory DataModel.fromJson(Map<String, dynamic> json) {
return DataModel(
measure: List<DataTitle>.from(
json['measure'].map((c) => DataTitle.fromJson(c)).toList()),
);
}
}
class DataTitle {
DataTitle(
{required this.number,
required this.firstarray,
required this.secondarray});
int? number;
List<double>? firstarray;
List<double>? secondarray;
DataTitle.fromJson(Map<String, dynamic> json) {
number = json['count'];
firstarray = json['range_array'] == null
? []
: List<double>.from(json['range_array'].map((x) => x.toDouble()));
secondarray = json['force_array'] == null
? []
: List<double>.from(json['force_array'].map((x) => x.toDouble()));
}
#override
String toString() {
return 'DATA TITLE{Count: $number, RangeArray: $firstarray, ForceArray: $secondarray}';
}
}
Here is the where i want to display the Chart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:convert';
import 'package:read_local_json/measure_data_model.dart';
import 'dart:async' show Future;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'JSON',
home: Home(),
);
}
}
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
HomeState createState() => HomeState();
}
class HomeState extends State<Home> {
Future loadData() async {
final jsonString = await rootBundle.loadString('assets/measurelist.json');
final decodedJson = json.decode(jsonString);
List<DataTitle> dataTileList = (decodedJson['measure'] as List)
.map((jsonElement) => DataTitle.fromJson(jsonElement))
.toList();
print(dataTileList.first);
print(dataTileList.last);
}
#override
void initState() {
super.initState();
loadData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('JSON Chart'),
),
body: const Center(
child: Text('JSON Chart'),
),
);
}
}
The JSON data can be converted to a list with the help of the json.decode function.
import 'dart:convert';
final List<Measure> measures = (json.decode(jsonstring)['measure'] as List).map((i) => Measure.fromJson(i)).toList();
class Measure {
final int count;
final List<double> range_array;
final List<double> force_array;
Measure({this.count, this.range_array, this.force_array});
factory Measure.fromJson(Map<String, dynamic> json) {
return Measure(
count: json['count'],
range_array: json['range_array'],
force_array: json['force_array'],
);
}
}
After that, use a charts package to draw the line chart.
LineChart(
data: LineChartData(
points: measures[0].count.toList().asMap().entries.map((key) => DataPoint(key.key.toDouble(), measures[0].force_array[key.key])).toList(),
),
);
I have tried to put JSON data in flutter chart, I used syncfusion_flutter_charts library but its not working and its only showing y axis point but not x axis points any one can help me the display json data in flutter SfCartesianChart
Or
help me in put this data in other charts of flutter
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:syncfusion_flutter_charts/charts.dart';
class Graph extends StatefulWidget {
#override
_GraphState createState() => _GraphState();
}
class _GraphState extends State<Graph> {
Future<String> fetchUsers() async {
String url = 'http://example.com/json.php';
var response = await http.get(url);
print(response.body);
return response.body.toString();
}
#override
void initState() {
loadSalesData();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Graph"),
),
body: SfCartesianChart(
title: ChartTitle(text: 'Leads'),
primaryXAxis: CategoryAxis(),
series: <LineSeries<LinearSales, String>>[
LineSeries<LinearSales, String>(
dataSource: chartData,
xValueMapper: (LinearSales sales, _) => sales.name,
yValueMapper: (LinearSales sales, _) => sales.leads,
)
]));
}
List<LinearSales> chartData = [];
Future loadSalesData() async {
final jsonResponse = json.decode(jsonString);
// print(jsonString);
// print(jsonResponse);
setState(() {
for (Map i in jsonResponse) chartData.add(LinearSales.fromJson(i));
});
}
}
class LinearSales {
LinearSales(this.name, this.leads);
final String name;
final int leads;
factory LinearSales.fromJson(Map<String, dynamic> parsedJson) {
//print(parsedJson);
return LinearSales(
parsedJson['name'],
parsedJson['leads'],
);
}
}
I resolve this problem. refer int.parse()
class LinearSales {
LinearSales(this.name, this.leads);
final String name;
final int leads;
factory LinearSales.fromJson(Map<String, dynamic> parsedJson) {
//print(parsedJson);
return LinearSales(
parsedJson['name'],
int.parse(parsedJson['leads']),
);
}
}
Here is a complete code snippet that should demonstrate the issue that I am bumping into.
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
SystemChrome.setEnabledSystemUIOverlays([]);
runApp(
MaterialApp(
home: MyHomePage(),
),
);
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key,}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
Future<latestVersion> fetchAlbum() async {
final response = await http.get('https://api.jsonbin.io/b/5fd25941bef8b7699e57dce9');
if (response.statusCode == 200) {
print('yay');
return latestVersion.fromJson(jsonDecode(response.body));
} else {
print('nay');
throw Exception('Failed to load version');
}
}
class latestVersion {
final String title;
final String version;
latestVersion({this.version, this.title});
factory latestVersion.fromJson(Map<String, dynamic> json) {
return latestVersion(version: json['version'], title: json['title'],
);
}
}
class _MyHomePageState extends State<MyHomePage> {
static Future<latestVersion> futureAlbum;
#override
void initState() {
super.initState();
futureAlbum = fetchAlbum();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.yellow,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(''),
Text('CURRENT'),
Text('---------'),
Text('0.37'),
Text(''),
Text('LATEST'),
Text('--------'),
Text(latestVersion.version),
Text(''),
Text(''),
],
),
),
);
}
}
When trying to run this code, I get an error at line 76.
"instance member 'version' cannot be accessed using static access"
How exactly can I access this json-decoded variable? Thank you in advance. I'm new to working with asynchronous functions and Future and would appreciate any help that can be given.
The error means version is not a Static variable. So to access it like this LatestVersion.version either make version a static variable or
Replace
Text(LatestVersion.version),
with
Text(LatestVersion().version),
If everything else is correct in your code the above should work.
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';
class HomePage extends StatefulWidget {
#override
HomePageState createState() => HomePageState();
}
class HomePageState extends State<HomePage> {
List items;
Future<String> getData() async {
var response = await http.get(
'https://api.torn.com/torn/?selections=items&key=7PnSA9HkVB5B6eAK');
this.setState(() {
Map items = json.decode(response.body);
print(items);
});
}
#override
void initState() {
this.getData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: items == null ? 0 : items.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Text(items[index]['name']),
);
},
),
);
}
}
As far as i know we can get Json in two forms, first is List and second is a Map.
In my case i received a Map with all data i need but unfortunately i dont know how properly display that.
From print i received data but nothing happen on screen.
You must not re-define items. You need to set it. It will look like this:
setState(() {
items = jsonDecode(response.body);
print(items);
});
Check the setState inside your getData method, you are creating a new items variable instead of assigning the new value to it. Try this one.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class HomePage extends StatefulWidget {
#override
HomePageState createState() => HomePageState();
}
class HomePageState extends State<HomePage> {
Map items = {};
Future<void> getData() async {
http.Response res = await http.get(
"https://api.torn.com/torn/?selections=items&key=7PnSA9HkVB5B6eAK",
);
setState(() => items = jsonDecode(res.body)["items"]);
print(items);
}
#override
void initState() {
getData();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
index++;
return Card(
child: Text(items[index.toString()]["name"] ?? "Empty"),
);
},
),
);
}
}