Flutter / JSON: instance member cannot be accessed using static access - json

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.

Related

Null is not a subtype of type 'int'

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'].

Exception has occurred, unexpected character at char 1

I've been struggling with this for quite a while. I'm just trying to read text from JSON and place it in Text, but it won't allow me, and it only throws out this error which I can't find a solution to.
Error :
I made a separate class quotes.dart which contains only this
final String author;
final String quote;
Quotes({required this.author, required this.quote});
factory Quotes.fromJson(Map<String, dynamic> data) {
return Quotes(author: data["author"], quote: data["quote"]);
}
Map<String, dynamic> toJson() {
return {
"author": author,
"quote": quote,
};
}
}
And in main I've got this:
// ignore_for_file: unnecessary_string_interpolations
import 'quotes.dart';
import 'package:flutter/material.dart';
import 'dart:convert';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:todo_task/quotes.dart';
void main() {
runApp(const MaterialApp(
home: todo_task(),
));
}
class todo_task extends StatefulWidget {
const todo_task({Key? key}) : super(key: key);
#override
_todo_taskState createState() => _todo_taskState();
}
class _todo_taskState extends State<todo_task> {
Map<String, dynamic> userMap = jsonDecode('assets/json/quotes.json');
// user = Quotes.fromJson(userMap);
.
.
.
Align(
alignment: Alignment.topRight,
child: Padding(
padding: EdgeInsets.fromLTRB(0.0, 110.0, 5.0, 0.0),
child: Text('${userMap['author']}',
style: TextStyle(
color: Colors.white,
fontSize: 20,
)),
)),
Also, my JSON file is simple
{
"author":"Albert Einstein",
"quote":"We cannot solve problems with the kind of thinking we employed when we came up with them."
}

Cant transform json to listview in flutter

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"),
);
},
),
);
}
}

How to use response body in another screen

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();
}
}

When launching the application the string appears as null

As the title has said, whenever I run the flutter application in my phone (debug mode atm, I don't know if it will work correctly in release mode). The dndguide.toString() appears as null. However, upon a hot reload the string appears normally. Is there a way to avoid this and make it work correctly upon launching? I suspect I put the loadjson() call in the wrong location, but I've tried shaping the code so that the function is called in different areas and no success.
Here is the code for the application:
import 'package:flutter/material.dart';
import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;
import 'dart:convert';
void main() => runApp(MyApp());
var dndguide;
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<String> _loadAsset() async {
return await rootBundle.loadString('assets/data/HDARG.json');
}
Future loadjson() async {
String jsonString = await _loadAsset();
final jsonResponse = json.decode(jsonString);
dndguide = jsonResponse;
}
#override
Widget build(BuildContext context) {
loadjson();
var scrollcontroller;
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: MediaQuery.of(context).size.height - 24,
margin: EdgeInsets.only(top: 24.0),
width: MediaQuery.of(context).size.width * .90,
child: SingleChildScrollView(
physics: BouncingScrollPhysics(),
controller: scrollcontroller,
scrollDirection: Axis.vertical,
child: Text(dndguide.toString()),
),
),
],
),
),
);
}
}
The json response is called asynchronously, which why the first time it gives null and after hot reloading it appears successfully. You should put some placeholder value into your dndguide variable or call the json in the initState() function of your _MyHomePageState instead of calling it during build process:
#override
void initState() {
super.initState();
loadjson();
}