Conversation
|
@parlough Ok - I've updated the code and resubmitted this. PTAL. |
There was a problem hiding this comment.
Code Review
The pull request successfully addresses compilation issues, JSON decoding cast warnings, and incorporates immutable data class best practices as outlined in the description. The changes primarily involve updating code examples and tutorial content to reflect these improvements, ensuring consistency and correctness across the project files. However, there are a few areas where further refinement can enhance code quality and tutorial clarity.
| return Padding( | ||
| padding: const EdgeInsets.all(8.0), | ||
| child: Column( | ||
| spacing: 10.0, |
| @override | ||
| Widget build(BuildContext context) { | ||
| return Padding( | ||
| padding: const EdgeInsets.all(8.0), |
| static Summary fromJson(Map<String, Object?> json) { | ||
| return switch (json) { | ||
| { | ||
| 'titles': final Map<String, Object?> titles, | ||
| 'pageid': final int pageid, | ||
| 'extract': final String extract, | ||
| 'extract_html': final String extractHtml, | ||
| 'thumbnail': final Map<String, Object?> thumbnail, | ||
| 'originalimage': final Map<String, Object?> originalImage, | ||
| 'lang': final String lang, | ||
| 'dir': final String dir, | ||
| 'description': final String description, | ||
| 'content_urls': { | ||
| 'desktop': {'page': final String url}, | ||
| 'mobile': {'page': String _}, | ||
| }, | ||
| } => | ||
| Summary( | ||
| titles: TitlesSet.fromJson(titles), | ||
| pageid: pageid, | ||
| extract: extract, | ||
| extractHtml: extractHtml, | ||
| thumbnail: ImageFile.fromJson(thumbnail), | ||
| originalImage: ImageFile.fromJson(originalImage), | ||
| lang: lang, | ||
| dir: dir, | ||
| description: description, | ||
| url: url, | ||
| ), | ||
| { | ||
| 'titles': final Map<String, Object?> titles, | ||
| 'pageid': final int pageid, | ||
| 'extract': final String extract, | ||
| 'extract_html': final String extractHtml, | ||
| 'lang': final String lang, | ||
| 'dir': final String dir, | ||
| 'description': final String description, | ||
| 'content_urls': { | ||
| 'desktop': {'page': final String url}, | ||
| 'mobile': {'page': String _}, | ||
| }, | ||
| } => | ||
| Summary( | ||
| titles: TitlesSet.fromJson(titles), | ||
| pageid: pageid, | ||
| extract: extract, | ||
| extractHtml: extractHtml, | ||
| lang: lang, | ||
| dir: dir, | ||
| description: description, | ||
| url: url, | ||
| ), | ||
| { | ||
| 'titles': final Map<String, Object?> titles, | ||
| 'pageid': final int pageid, | ||
| 'extract': final String extract, | ||
| 'extract_html': final String extractHtml, | ||
| 'lang': final String lang, | ||
| 'dir': final String dir, | ||
| 'content_urls': { | ||
| 'desktop': {'page': final String url}, | ||
| 'mobile': {'page': String _}, | ||
| }, | ||
| } => | ||
| Summary( | ||
| titles: TitlesSet.fromJson(titles), | ||
| pageid: pageid, | ||
| extract: extract, | ||
| extractHtml: extractHtml, | ||
| lang: lang, | ||
| dir: dir, | ||
| url: url, | ||
| ), | ||
| _ => throw FormatException('Could not deserialize Summary, json=$json'), | ||
| }; |
There was a problem hiding this comment.
The Summary.fromJson factory constructor uses a verbose switch expression with three very similar cases to handle the presence or absence of optional fields like thumbnail, originalImage, and description. This approach leads to significant code duplication and can be difficult to maintain if more optional fields are added.
Consider refactoring this method to parse required fields first, and then conditionally parse optional fields, assigning null if they are not present in the JSON. This would make the parsing logic more concise and easier to read.
|
Visit the preview URL for this PR (updated for commit 02cc439): https://flutter-docs-prod--pr13196-resubmit-13156-a7wk8rb5.web.app |
There was a problem hiding this comment.
Thanks for coming back to this @lamek! I appreciate it :D
The other files look good to me, but the steps and code snippets don't align in listenable-builder.md yet. I left comments on the first few cases, but it continues on from there.
Let me know if you have any questions, hit any issues, or would like to go through it together. Thanks again!
Also don't worry about it for this PR, but I imagine we can reuse the same file for more steps. Docregions can be opened and closed multiple times within the same file. When I have time, I'll open a PR consolidating some excerpts with some examples.
| ### Set up the `fetchArticle` method | ||
|
|
||
| Add the `getRandomArticleSummary` that fetches data and manages state updates: | ||
| Add the `fetchArticle` that fetches data and manages state updates: |
There was a problem hiding this comment.
| Add the `fetchArticle` that fetches data and manages state updates: | |
| Add the `fetchArticle` method that fetches data and manages state updates: |
| appBar: AppBar(title: const Text('Wikipedia Flutter')), | ||
| body: Center( | ||
| child: ListenableBuilder( | ||
| listenable: viewModel, | ||
| builder: (context, _) { | ||
| return switch (( |
There was a problem hiding this comment.
Seems this all shouldn't be included yet, until the next few steps. For now, can just include the center ed text to keep the step focused on the instantiating the model.
| ```dart | ||
| class ArticleView extends StatelessWidget { | ||
| ArticleView({super.key}); | ||
| class ArticlePage extends StatelessWidget { |
There was a problem hiding this comment.
Looks like this isn't the intended code snippet here for here. The text no longer matches up.
| ```dart | ||
| class ArticleView extends StatelessWidget { | ||
| ArticleView({super.key}); | ||
| class ArticlePage extends StatelessWidget { |
There was a problem hiding this comment.
Same here, after the update, this code snippet doesn't match. Seems like it maybe should be the article view code currently in step4b_main.dart?
There was a problem hiding this comment.
Seems most added code snippets in this lesson no longer match the text. Perhaps they're referencing the incorrect source file/region? I left a comment on the first few, but it continues on after.
| // ignore_for_file: avoid_dynamic_calls | ||
|
|
||
| import 'dart:convert'; |
There was a problem hiding this comment.
This ignore shouldn't be needed. I don't see any code that would trigger it.
| // ignore_for_file: avoid_dynamic_calls | |
| import 'dart:convert'; | |
| import 'dart:convert'; |
There was a problem hiding this comment.
You can delete this file. We have a shared analysis config at the root of the /examples directory.
| // Image path and size, but doesn't contain any Wikipedia descriptions. | ||
| /// | ||
| /// For images with metadata, see [WikipediaImage] |
There was a problem hiding this comment.
This references a class named WikipediaImage, but I don't see that anymore. Perhaps its left over from an old iteration?
To avoid confusion for now, consider removing it.
| // Image path and size, but doesn't contain any Wikipedia descriptions. | |
| /// | |
| /// For images with metadata, see [WikipediaImage] | |
| // Image path and size, but doesn't contain any Wikipedia descriptions. |
| bool get hasImage => originalImage != null && thumbnail != null; | ||
|
|
||
| /// Returns a new [Summary] instance and imports its values from a JSON map | ||
| static Summary fromJson(Map<String, Object?> json) { |
There was a problem hiding this comment.
This is pre-existing and we can improve it later, but as a note, this switch with multiple very similar cases is hard to understand and maintain.
| /// Titles | ||
| final TitlesSet titles; | ||
|
|
||
| /// Page ID | ||
| final int pageid; | ||
|
|
||
| /// Extract | ||
| final String extract; | ||
|
|
||
| /// Extract HTML | ||
| final String extractHtml; | ||
|
|
||
| /// Thumbnail image | ||
| final ImageFile? thumbnail; | ||
|
|
||
| /// Original image | ||
| final ImageFile? originalImage; | ||
|
|
||
| /// Language | ||
| final String lang; | ||
|
|
||
| /// Directionality | ||
| final String dir; | ||
|
|
||
| /// Description | ||
| final String? description; | ||
|
|
||
| /// URL | ||
| final String url; | ||
|
|
||
| bool get hasImage => originalImage != null && thumbnail != null; |
There was a problem hiding this comment.
I'd either update the doc comments to more closely align with Effective Dart or remove them.
| /// Titles | |
| final TitlesSet titles; | |
| /// Page ID | |
| final int pageid; | |
| /// Extract | |
| final String extract; | |
| /// Extract HTML | |
| final String extractHtml; | |
| /// Thumbnail image | |
| final ImageFile? thumbnail; | |
| /// Original image | |
| final ImageFile? originalImage; | |
| /// Language | |
| final String lang; | |
| /// Directionality | |
| final String dir; | |
| /// Description | |
| final String? description; | |
| /// URL | |
| final String url; | |
| bool get hasImage => originalImage != null && thumbnail != null; | |
| /// The title information of this article. | |
| final TitlesSet titles; | |
| /// The page ID of this article. | |
| final int pageid; | |
| /// The first few sentences of the article in plain text. | |
| final String extract; | |
| /// The first few sentences of the article in HTML format. | |
| final String extractHtml; | |
| /// A thumbnail-sized version of the article's primary image, if available. | |
| final ImageFile? thumbnail; | |
| /// The original full-sized article's primary image, if available. | |
| final ImageFile? originalImage; | |
| /// The language code of the article's content, such as "en" for English. | |
| final String lang; | |
| /// The text directionality of the article's content, such as "ltr" or "rtl". | |
| final String dir; | |
| /// A description of the article, if available. | |
| final String? description; | |
| /// The URL of the page. | |
| final String url; | |
| /// Whether this article has an image. | |
| bool get hasImage => originalImage != null && thumbnail != null; |
This resubmits PR #13156, and integrates fixes to resolve the reverted compilation issues, JSON decoding cast warnings, and immutable data class best practices.