Errata

Flutter and Dart Cookbook

Errata for Flutter and Dart Cookbook

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
Printed, PDF, ePub, Mobi, , Other Digital Version Page Page 9.9 Using a Column In the code
In the code

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Center Example')),
...

Should be 'Column Example'

Márton Urbán  Jan 31, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 10.1 Using the Google Fonts Package
In the code

4 minor mistakes:

1. no 'const' added to runApp(MyApp())
2. constructor doesn't have 'key' parameter (flutter recommends it and it was also there in your other codes)
3. Flutter info: 'bodyText1' is deprecated and shouldn't be used. Use bodyLarge instead. This feature was deprecated after v3.1.0-0.0.pre
(same for bodyText2, bodyMedium is recommended)
4. You pass title: 'Flutter and Dart Cookbook' to the widget, then you never use it

On github, the source codes do not match the chapthers (ex10-1.md should be 10-2, and ex10-2 should be 10-1.md).

Márton Urbán  Jan 31, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 10.2 Incorporating RichText
CODE

Quote from the section Discussion: "The example code makes use
of a media query"

But it actually doesn't. Global variable screenHeight is initialized, then in the MyRichText class it gets assigned a value by MediaQuery, but it's never referenced afterwards and the code doesn't make use of it:

double screenHeight = 0.0;
class MyRichText extends StatelessWidget {
const MyRichText({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
screenHeight = MediaQuery.of(context).size.height / 3;
...

Márton Urbán  Feb 01, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 11.1 Implementing a Vertical ListView
CODE

You have a whole class in your code, right at the beginning, which is never used:

class ListTileItem {
final String monthItem;
const ListTileItem(
this.monthItem,
);
}

You never actually created any ListTileItem instances.

Márton Urbán  Feb 01, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 11.2 Implementing a Horizontal ListView
CODE

Yet again, the same 'ListTileItem' class as in the previous section code is never used.

But maybe more importantly, you seem to be missing some important explanations, like why ListTile is not used with this ListView (compared to the previous section with the vertical list). Why isn't it enough to just change it to scrollDirection: Axis.horizontal, and leave everything else as it was in the previous section. I think this question comes to the serious reader's mind right away, and I myself of course researched it, but I think it would help your readers a lot if you elaborated on this in your book.

Márton Urbán  Feb 01, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 11.4 Adding a SliverList
CODE

In your code due to the missing constructor, default constructor is added automatically, therefore const is not possible this way:
---
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
...
---
RECOMMENDED (added constructor, now myApp can be const):
---
void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
...
----

And once again the argument 'Flutter and Dart Cookbook' is passed to the widget (as String title) and never used. This really is confusing for beginners, as it might not be clear to them that this 'title' is not at all the same as the other 'title' parameters in the widgets. I think with beginners (this book is for them), you must really be precise and not confuse them with redundant parameters.

Márton Urbán  Feb 02, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 12.2 Adding Page Navigation with Routes (Declarative)
whole section

Horrible, just horrible. I'm starting to question whether "author" is even a real programmer or just made a collection of scripts and pasted them into the book.

No explanation whatsoever as to why author used "routes" in one part of the code, and "onGenerateRoute" in other parts. Even more important, 0 mention about why (BuildContext _) was used instead of (BuildContext context) in one part of the code even though it is an important aspect to understand. Does author even understand how "his" code works? There is so much inconsistency and errors throughout the whole book, it really is clear that these examples were NOT written by the same programmer, but rather just collected them from the web. And he didn't even test these codes?? Unbelievable, really.
But at least he would be able to explain them... but it is clear he can't.
How is this useful to beginner Flutter programmers?

Author installs Flutter 3.3.3 in the book, but still uses headline4 instead of headlineMedium in thie section (and in some other sections too), even though headline4 was deprecated long before Flutter 3.3.

Márton Urbán  Feb 11, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 12.3 Implementing a Navigation Drawer
CODE AND EXPLANATION

You go into detailed explanation about adding the drawer to the right side, which automatically adds the back button to the left. But have you even tested your own code? The navigation drawer doesn't close when using the back button. So user doesn't even see that anything has changed unless they close the drawer manually. So you need to pop it for DemoPageFour like this:

onTap: () {
Navigator.of(context).pop(); // or Navigator.pop(context)
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => const DemoPageFour()),
);
}

Márton Urbán  Feb 11, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 12.2 Adding Page Navigation with Routes (Declarative)
code

return MaterialPageRoute<void>(builder: builder, settings: settings);

Yet another unnecessary passed argument that just confuses the reader.
The code works fine without it:

return MaterialPageRoute<void>(builder: builder);

Márton Urbán  Feb 13, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 12.4 Working with Tabs
IN THE CODE

Yet again, passing an argument that is never used later in the class (title):
home: const MyHomePage(title: 'Flutter and Dart Cookbook')

Márton Urbán  Feb 13, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 12.6 Using Keys to Pass Information
WHOLE SECTION

The section is titled "Using Keys to Pass Information", but author has obviously no idea what keys are or how to use them. He doesn't even demonstrate the usage of keys in his code. He references a video from the Flutter team for the readers to watch.

For the example code, he starts by:
"Use keys to pass information between stateful widgets. Keys are typically
used to pass state as a key/value pair.
Here’s an example to demonstrate information passing using keys and
named parameters:"

Then author pasted a code into the book that does NOT use the keys to pass any information. 2 named parameters are used to pass arguments (title and name), and that's it.

This book should not have been published, O'Reilly, I beg you to please take a look at it, author doesn't even check the unconfirmed erratas, even though there are a lot, and I'm sure more are coming...

Márton Urbán  Feb 13, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 12.6 Using Keys to Pass Information
Discussion

Author actually mixes up keys with named parameters, further proof he doesn't understand basic Flutter terms:
"In this example, we use keys to pass information between the parent class
and the child."

Keys are never used in the example code, the information is passed via the named parameters "name" and "title".

The whole "explanation" does not help the reader at all, especially after all the confusion in author's mind.

Márton Urbán  Feb 14, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 13.4
CODE

Multiple mistakes in the code, it is unbelievable that author doesn't test his own code (or now I'm starting to think that he can't debug it due to serious lack of knowledge):

class MyData {
final String items = '{"data": [
{ "title": "January" },
{ "title": "February" },
{ "title": "March" },
] }';
}

Code doesn't even compile as author doesn't use the multi-line string literal.
BUT even if we fix this:

class MyData {
final String items = '''{"data": [
{ "title": "January" },
{ "title": "February" },
{ "title": "March" },
] }''';
}

Now the code will compile, but the app won't work. After debugging, the exception happens at:

final jsonResponse = json.decode(jsonString);

That is because the json decode won't work due to the comma after the last list item. Final fixed code:

class MyData {
final String items = '''{"data": [
{ "title": "January" },
{ "title": "February" },
{ "title": "March" } // removed comma to make it work
] }''';
}

Márton Urbán  Feb 23, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 13.4
CODE

Even the compiler warns about this unneeded print statement:
print(dataSeries.dataModel[0].title);

There is also an unnecessary 'key: null' passed in the code.

I also really don't understand why author doesn't even mention the use of 'snapshot' in the explanation of this code (or anywhere in the book), even though it is heavily used in the example code.

Márton Urbán  Feb 25, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 13.5 Consuming a JSON Dataset from the Assets Folder
CODE

Yet another code that won't compile, this time due to an undefined function:

Future<String> _loadAssetData() async {
final AssetBundle rootBundle = _initRootBundle(); // undefined function
return await rootBundle.loadString('assets/example2.json');
}

Márton Urbán  Feb 26, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page SECTION 14.3 Performing Integration Testing with Flutter Driver
CODE

Even the code used for testing has multiple mistakes in the book:

setUpAll(()) async { // unneeded closing bracket ')'
...
tearDownAll(()) async { // unneeded closing bracket ')'
...
await driver.enterText("Martha Kent") // missing semicolon
...

Márton Urbán  Feb 27, 2023 
PDF, Other Digital Version Page 5.5 Adding a Class Interface
in the code portion

@override
void setMediaId(String mediaId) {
myType = mediaId; // ERROR
}

It should be: myId = mediaId;

The only reason it doesn't affect the code is because the setter isn't even actually used in the code. Maybe it should be used as beginners will be confused why the setters are never used. Example usage would be:

Book(String mediaTitle, String mediaType, String mediaId) {
setMediaTitle(mediaTitle);
setMediaType(mediaType);
setMediaId(mediaId);
}

(in your code the variables are directly set, so the 3 setters are actually never used)

Márton Urbán  Jan 29, 2023 
PDF, Other Digital Version Page 5.6 Adding a Class Mixin
Last sentence of "Discussion"

"Figure 5-8 outlines how classes can be extended through the mixin keyword."

This is true, but you don't actually use the mixin keyword in the example code anywhere:

abstract class SnickersOriginal {
bool hasHazelnut = true;
bool hasRice = false;
bool hasAlmond = false;
}

abstract class SnickersCrisp {
bool hasHazelnut = true;
bool hasRice = true;
bool hasAlmond = false;
}

Maybe change it to:

mixin SnickersOriginal {
bool hasHazelnut = true;
bool hasRice = false;
bool hasAlmond = false;
}

mixin SnickersCrisp {
bool hasHazelnut = true;
bool hasRice = true;
bool hasAlmond = false;
}

Or possibly mention that both approaches work here, but since the chapter is about mixins and you actually mention the keyword in the discussion, usage of the actual keyword in the code is suggested.

Márton Urbán  Jan 30, 2023 
ePub Page 6.1 Adding the Dart Test Package to Your Application
Solution - 1st paragraph

The paragraph says: "We have already defined a template Flutter application earlier (see the chapter introduction)" but not chapter introduction in the book...

Anonymous  Mar 13, 2023 
PDF, Other Digital Version Page 6.3 Running Unit Tests in Your Dart Application
in the code portion

Missing import of:

import 'package:test/test.dart';

I'm sure this was meant to be there as this import is actually added in later tests in your book.

This import should also be explained in 6.1 where you mention:
dart pub add test --dev

After that you have this note right away:
"If you are using DartPad, you will need to use:
import 'package:flutter_test/flutter_test.dart';"

But you never mention the basic import after adding test to dev_dependencies.

Márton Urbán  Jan 30, 2023 
PDF, Other Digital Version Page 7.2 Creating a Boilerplate Flutter Project
"To create a plug-in:"

Your example:

flutter create -t plugin my_awesome_plugin --platforms web --platform android

Your NOTE:
"When creating a plug-in, you must specify the platform to be supported. Each platform
to be added requires the addition of the --platform prefix."

That is not needed anymore, recommended usage (copied from flutter.dev):

flutter create -t plugin my_awesome_plugin --platforms=web,android,ios

Márton Urbán  Jan 30, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page 9.10 Using a Row
Whole section is strange

Expanded(
child: Container(
height: 50,
width: 200, // this doesn't belong here, will be ignored in this case
color: Colors.red,
child: const Center(
child: Text("50"),
),
),
),
...
Quote from the book:
"The example applies a constraint to the widget displayed, so it will dynamically adjust to the screen size. To understand the options applicable to constraints, consult the Flutter documentation."

It's really not clear which constraint you mean here. You wrapped the 3 containers in an Expanded widget, yet you still added width=200 to all 3 containers which doesn't make any sense as they will be ignored by the compiler (when used in a row as in the example). The width parameter could be anything, even 3 different values, the outcome wouldn't change (because of the Expanded widgets under Row). To me it looks like perhaps you didn't plan to use the Expanded widget here because you don't even mention it in the discussion, but the Expanded widget is actually taught in the next section (9.11 Using an Expanded Widget).

Please advise!

Márton Urbán  Jan 31, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page 9.3 Refactoring Flutter Widgets
In both code blocks

Image.network('ht tps://oreil.ly/O4PEn')
(had to add space, because URLs are not allowed here)

The image is never loaded due most likely to the redirect. Same thing for the second code block in the chapter (the refeactored one). If you use the redirected final url, it works:

Image.network('ht tps://images.unsplash.com/photo-1499028344343-cd173ffc68a9')
(had to add space, because URLs are not allowed here)

I wonder if there is a quick solution to load redirected images, I haven't had any success so far.

Márton Urbán  Jan 31, 2023 
Printed, PDF, ePub, Mobi, , Other Digital Version Page 9.9 Using a Column
In the code

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Center Example')),
body: _buildCenterWidget(),
);
}
Widget _buildCenterWidget() {
return Column(
...

Just a typo, I'm sure you meant _buildColumnWidget, not _buildCenterWidget

Márton Urbán  Jan 31, 2023 
Printed Page 47
Near the bottom, in setMediaId()

Assignment should be to myId.

Jeff Phillips  Aug 05, 2023 
Printed Page 50
Top third

SnickersOriginal and SnickersCrisp classes should have "mixin" rather than "abstract" as the first token in the class declaration. Found in Dart 3.0.6 stable on Linux x64.

Jeff Phillips  Aug 05, 2023