-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix example on 'Parse JSON in the background' page #6768
Comments
@Whisper40 for the case you are reporting the code ignores avoid-using-cast imho the issue should be |
I don't understand why the documentation is wrong, if a newbie comes to it it has to be right.. |
@Whisper40 There is a silver lining, |
The reason some sample code is wrong is that Dart had evolved over time, including introducing some breaking changes, so code that was correct when it was written does not always work in new versions of Dart. |
Flutter uses Dart, so yes the official documentation has to follow change. |
I'm not saying it shouldn't. I'm saying that in practice, documentation gets written at a point in time, and can become incorrect, and then someone needs to a) discover the places that are no longer correct, and b) fix them, and that process is not automatic or foolproof. (I have filled an issue to track a possible approach to automate (a)).
Yes: https://github.com/flutter/website
Being open source does not mean it is error-proof or self-updating. |
this is awesome please consider this pr (@Whisper40 you may try it if you like) I'm not good with words but I think a possible "misstep" for beginners |
@iapicca I'm trying your PR, it compiles without errors now, but i have an error with the parsePhotos ( in my case parsePosts). The loader is displayed but then it freezes and throw the icon exception List<Post> parsePosts(String responseBody) {
final parsed = jsonDecode(responseBody) as List;
return [for (final json in parsed) Post.fromJson(json)];
} |
good
@Whisper40 also make sure you are using the latest |
Json here : https://jsonplaceholder.typicode.com/posts
http_service.dart : import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import '../models/post_model.dart';
class HttpService {
// final uri = Uri.parse('https://jsonplaceholder.typicode.com') as String;
// final String postsURL = '/posts';
// final Map<String, String> headers = {
// 'Content-Type': 'application/json'
// };
List<Post> parsePosts(String responseBody) {
final parsed = jsonDecode(responseBody) as List;
return [for (final json in parsed) Post.fromJson(json)];
}
Future<List<Post>> fetchPosts(http.Client client) async {
final uri = Uri.parse('https://jsonplaceholder.typicode.com/posts');
final response = await client.get(uri);
if (response.statusCode == 200) {
return compute(parsePosts,response.body);
} else {
throw Exception("Failed to load posts ${response.statusCode}");
}
}
} posts_page.dart : import 'package:flutter/material.dart';
import '../models/post_model.dart';
import '../services/http_service.dart';
import 'package:http/http.dart' as http;
class PostsPage extends StatelessWidget {
final String title;
final HttpService httpService = HttpService();
PostsPage({Key? key, required this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: FutureBuilder<List<Post>>(
future: httpService.fetchPosts(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) {
print(snapshot.error);
return const Center(child: Icon(Icons.error));
}
return snapshot.hasData
? PostsList(posts: snapshot.data!)
: const Center(child: CircularProgressIndicator());
},
),
);
}
}
class PostsList extends StatelessWidget {
final List<Post> posts;
const PostsList({Key? key, required this.posts}) : super(key: key);
@override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: posts.length,
itemBuilder: (context, index) {
return Image.network(posts[index].title);
},
);
}
} post_model.dart : import 'package:flutter/foundation.dart';
import 'package:json_annotation/json_annotation.dart';
part 'post_model.g.dart';
@JsonSerializable()
@immutable
class Post {
const Post({
required this.userId,
required this.id,
required this.title,
required this.body,
});
factory Post.fromJson(Map<String, dynamic?> json) => _$PostFromJson(json);
Map<String, dynamic> toJson() => _$PostToJson(this);
final int userId, id;
final String title, body;
} |
@Whisper40
here is your code working fixed codeimport 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(const MaterialApp(home: PostsPage(title: 'title')));
class HttpService {
static List<Post> _parsePosts(String responseBody) {
final parsed = jsonDecode(responseBody) as List;
return [for (final json in parsed) Post.fromJson(json)];
}
static Future<List<Post>> fetchPosts(http.Client client) async {
final uri = Uri.parse('https://jsonplaceholder.typicode.com/posts');
final response = await client.get(uri);
if (response.statusCode == 200) {
return compute(_parsePosts, response.body);
} else {
throw Exception("Failed to load posts ${response.statusCode}");
}
}
}
@immutable
class Post {
const Post({
required this.userId,
required this.id,
required this.title,
required this.body,
});
factory Post.fromJson(Map<String, Object?> json) {
return Post(
body: json['body'] as String,
id: json['id'] as int,
userId: json['userId'] as int,
title: json['title'] as String,
);
}
final int userId, id;
final String title, body;
}
class PostsPage extends StatelessWidget {
final String title;
const PostsPage({Key? key, required this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: FutureBuilder<List<Post>>(
future: HttpService.fetchPosts(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) {
print(snapshot.error);
return const Center(child: Icon(Icons.error));
}
return snapshot.hasData
? PostsList(posts: snapshot.data!)
: const Center(child: CircularProgressIndicator());
},
),
);
}
}
class PostsList extends StatelessWidget {
final List<Post> posts;
const PostsList({Key? key, required this.posts}) : super(key: key);
@override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: posts.length,
itemBuilder: (context, index) {
return Card(
child: Column(
children: [
Center(
child: Text(posts[index].title),
),
Center(
child: Text(posts[index].body),
)
],
),
);
},
);
}
}
bonus...
|
Thanks for your correction ! Now it works, i will take for sure a look at freezed ! |
@Whisper40 |
sorry guys I gave up on the PR,
imho the reason is nobody submits pr to update code samples and such because it's a very bad experience |
Transferring this issue to website repo, as this is more likely to be address there. |
This recipe appears to have most of the changes suggested in your initial PR. The example shown works. Closing this issue. If this is still a concern, please open a new issue and refer back to this one. Thanks! |
Steps to Reproduce
Just follow what is writed there : https://docs.flutter.dev/cookbook/networking/background-parsing
Expected results:
The parsePhotos should not produce errors
Actual results:
Actually this method is all in red. I tried with and without this :
My code :
The text was updated successfully, but these errors were encountered: