Use `@required` for onPressed and onChanged (#4534)

We now use the `@required` annotation to encourage developers to
explicitly set onPressed and onChanged callbacks to null when that would
disable the widget.

Fixes #287
diff --git a/dev/manual_tests/pageable_list.dart b/dev/manual_tests/pageable_list.dart
index 49ad79b..5f5c60a 100644
--- a/dev/manual_tests/pageable_list.dart
+++ b/dev/manual_tests/pageable_list.dart
@@ -103,7 +103,8 @@
           child: new Row(
             children: <Widget>[
               new Flexible(child: new Text('Scrolling wraps around')),
-              new Checkbox(value: itemsWrap)
+              // TODO(abarth): Actually make this checkbox change this value.
+              new Checkbox(value: itemsWrap, onChanged: null)
             ]
           )
         )
diff --git a/examples/flutter_gallery/lib/demo/buttons_demo.dart b/examples/flutter_gallery/lib/demo/buttons_demo.dart
index 70b9922..eecc902 100644
--- a/examples/flutter_gallery/lib/demo/buttons_demo.dart
+++ b/examples/flutter_gallery/lib/demo/buttons_demo.dart
@@ -106,7 +106,8 @@
             }
           ),
           new RaisedButton(
-            child: new Text('DISABLED')
+            child: new Text('DISABLED'),
+            onPressed: null
           )
         ]
       )
@@ -126,7 +127,8 @@
             }
           ),
           new FlatButton(
-            child: new Text('DISABLED')
+            child: new Text('DISABLED'),
+            onPressed: null
           )
         ]
       )
@@ -173,7 +175,8 @@
             color: iconButtonToggle ? Theme.of(context).primaryColor : null
           ),
           new IconButton(
-            icon: Icons.thumb_up
+            icon: Icons.thumb_up,
+            onPressed: null
           )
         ]
         .map((Widget button) => new SizedBox(width: 64.0, height: 64.0, child: button))
diff --git a/examples/flutter_gallery/lib/demo/persistent_bottom_sheet_demo.dart b/examples/flutter_gallery/lib/demo/persistent_bottom_sheet_demo.dart
index cb3c3b0..b99af8e 100644
--- a/examples/flutter_gallery/lib/demo/persistent_bottom_sheet_demo.dart
+++ b/examples/flutter_gallery/lib/demo/persistent_bottom_sheet_demo.dart
@@ -59,8 +59,9 @@
       key: _scaffoldKey,
       appBar: new AppBar(title: new Text('Persistent bottom sheet')),
       floatingActionButton: new FloatingActionButton(
-        child: new Icon(icon: Icons.add),
-        backgroundColor: Colors.redAccent[200]
+        onPressed: null,
+        backgroundColor: Colors.redAccent[200],
+        child: new Icon(icon: Icons.add)
       ),
       body: new Center(
         child: new RaisedButton(
diff --git a/examples/flutter_gallery/lib/demo/selection_controls_demo.dart b/examples/flutter_gallery/lib/demo/selection_controls_demo.dart
index 29213d7..e79e229 100644
--- a/examples/flutter_gallery/lib/demo/selection_controls_demo.dart
+++ b/examples/flutter_gallery/lib/demo/selection_controls_demo.dart
@@ -101,8 +101,8 @@
             mainAxisAlignment: MainAxisAlignment.collapse,
             children: <Widget>[
               // Disabled checkboxes
-              new Checkbox(value: true),
-              new Checkbox(value: false)
+              new Checkbox(value: true, onChanged: null),
+              new Checkbox(value: false, onChanged: null)
             ]
           )
         ]
@@ -142,15 +142,18 @@
             children: <Widget>[
               new Radio<int>(
                 value: 0,
-                groupValue: 0
+                groupValue: 0,
+                onChanged: null
               ),
               new Radio<int>(
                 value: 1,
-                groupValue: 0
+                groupValue: 0,
+                onChanged: null
               ),
               new Radio<int>(
                 value: 2,
-                groupValue: 0
+                groupValue: 0,
+                onChanged: null
               )
             ]
           )
@@ -171,8 +174,8 @@
             });
           }),
           // Disabled switches
-          new Switch(value: true),
-          new Switch(value: false)
+          new Switch(value: true, onChanged: null),
+          new Switch(value: false, onChanged: null)
         ]
       )
     );
diff --git a/examples/flutter_gallery/lib/demo/slider_demo.dart b/examples/flutter_gallery/lib/demo/slider_demo.dart
index 2ebe9dd..7ed55b7 100644
--- a/examples/flutter_gallery/lib/demo/slider_demo.dart
+++ b/examples/flutter_gallery/lib/demo/slider_demo.dart
@@ -34,7 +34,7 @@
               }
             )
           ),
-          new Center(child: new Slider(value: 0.25)),
+          new Center(child: new Slider(value: 0.25, onChanged: null)),
           new Center(
             child: new Slider(
               value: _discreteValue,
diff --git a/examples/flutter_gallery/lib/gallery/example_code.dart b/examples/flutter_gallery/lib/gallery/example_code.dart
index f444059..3538a6a 100644
--- a/examples/flutter_gallery/lib/gallery/example_code.dart
+++ b/examples/flutter_gallery/lib/gallery/example_code.dart
@@ -26,7 +26,8 @@
 // Buttons are disabled when onPressed isn't
 // specified or is null.
 new RaisedButton(
-  child: new Text('BUTTON TITLE')
+  child: new Text('BUTTON TITLE'),
+  onPressed: null
 );
 // END
 
@@ -44,7 +45,8 @@
 // Buttons are disabled when onPressed isn't
 // specified or is null.
 new FlatButton(
-  child: new Text('BUTTON TITLE')
+  child: new Text('BUTTON TITLE'),
+  onPressed: null
 );
 // END
 
@@ -97,7 +99,8 @@
     title: new Text('Demo')
   ),
   floatingActionButton: new FloatingActionButton(
-    child: new Icon(icon: Icons.add)
+    child: new Icon(icon: Icons.add),
+    onPressed: null
   )
 );
 // END
@@ -127,7 +130,7 @@
 // Create a disabled checkbox.
 // Checkboxes are disabled when onChanged isn't
 // specified or null.
-new Checkbox(value: false);
+new Checkbox(value: false, onChanged: null);
 // END
 
 
@@ -166,7 +169,8 @@
 // Creates a disabled radio button.
 new Radio<int>(
   value: 0,
-  groupValue: 0
+  groupValue: 0,
+  onChanged: null
 );
 // END
 
@@ -188,7 +192,7 @@
 // Create a disabled switch.
 // Switches are disabled when onChanged isn't
 // specified or null.
-new Switch(value: false);
+new Switch(value: false, onChanged: null);
 // END
   }
 }
diff --git a/examples/layers/widgets/media_query.dart b/examples/layers/widgets/media_query.dart
index 48bc064..fc2f51d 100644
--- a/examples/layers/widgets/media_query.dart
+++ b/examples/layers/widgets/media_query.dart
@@ -52,7 +52,8 @@
                   child: new Text(name)
                 ),
                 new IconButton(
-                  icon: Icons.more_vert
+                  icon: Icons.more_vert,
+                  onPressed: null
                 )
               ]
             )
diff --git a/packages/flutter/lib/src/material/button.dart b/packages/flutter/lib/src/material/button.dart
index d9f824d..c968743 100644
--- a/packages/flutter/lib/src/material/button.dart
+++ b/packages/flutter/lib/src/material/button.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'package:flutter/widgets.dart';
+import 'package:meta/meta.dart';
 
 import 'colors.dart';
 import 'constants.dart';
@@ -128,7 +129,7 @@
     this.minWidth,
     this.height,
     this.padding,
-    this.onPressed,
+    @required this.onPressed,
     this.child
   }) : super(key: key);
 
diff --git a/packages/flutter/lib/src/material/checkbox.dart b/packages/flutter/lib/src/material/checkbox.dart
index 3856acf..c490f93 100644
--- a/packages/flutter/lib/src/material/checkbox.dart
+++ b/packages/flutter/lib/src/material/checkbox.dart
@@ -6,6 +6,7 @@
 
 import 'package:flutter/rendering.dart';
 import 'package:flutter/widgets.dart';
+import 'package:meta/meta.dart';
 
 import 'constants.dart';
 import 'debug.dart';
@@ -42,19 +43,14 @@
   /// * [onChanged] is called when the value of the checkbox should change.
   Checkbox({
     Key key,
-    this.value,
-    this.activeColor,
-    this.onChanged
+    @required this.value,
+    @required this.onChanged,
+    this.activeColor
   }) : super(key: key);
 
   /// Whether this checkbox is checked.
   final bool value;
 
-  /// The color to use when this checkbox is checked.
-  ///
-  /// Defaults to accent color of the current [Theme].
-  final Color activeColor;
-
   /// Called when the value of the checkbox should change.
   ///
   /// The checkbox passes the new value to the callback but does not actually
@@ -64,6 +60,11 @@
   /// If null, the checkbox will be displayed as disabled.
   final ValueChanged<bool> onChanged;
 
+  /// The color to use when this checkbox is checked.
+  ///
+  /// Defaults to accent color of the current [Theme].
+  final Color activeColor;
+
   /// The width of a checkbox widget.
   static const double width = 18.0;
 
diff --git a/packages/flutter/lib/src/material/date_picker.dart b/packages/flutter/lib/src/material/date_picker.dart
index 8035d01..04081ff 100644
--- a/packages/flutter/lib/src/material/date_picker.dart
+++ b/packages/flutter/lib/src/material/date_picker.dart
@@ -8,6 +8,7 @@
 import 'package:flutter/widgets.dart';
 import 'package:intl/date_symbols.dart';
 import 'package:intl/intl.dart';
+import 'package:meta/meta.dart';
 
 import 'colors.dart';
 import 'debug.dart';
@@ -37,10 +38,10 @@
   /// [showDatePicker] to show a date picker in a dialog.
   DatePicker({
     Key key,
-    this.selectedDate,
-    this.onChanged,
-    this.firstDate,
-    this.lastDate
+    @required this.selectedDate,
+    @required this.onChanged,
+    @required this.firstDate,
+    @required this.lastDate
   }) : super(key: key) {
     assert(selectedDate != null);
     assert(firstDate != null);
@@ -134,9 +135,9 @@
 class _DatePickerHeader extends StatelessWidget {
   _DatePickerHeader({
     Key key,
-    this.selectedDate,
-    this.mode,
-    this.onModeChanged
+    @required this.selectedDate,
+    @required this.mode,
+    @required this.onModeChanged
   }) : super(key: key) {
     assert(selectedDate != null);
     assert(mode != null);
@@ -241,10 +242,10 @@
   /// Rarely used directly. Instead, typically used as part of a [DatePicker].
   DayPicker({
     Key key,
-    this.selectedDate,
-    this.currentDate,
-    this.onChanged,
-    this.displayedMonth
+    @required this.selectedDate,
+    @required this.currentDate,
+    @required this.onChanged,
+    @required this.displayedMonth
   }) : super(key: key) {
     assert(selectedDate != null);
     assert(currentDate != null);
@@ -365,10 +366,10 @@
   /// Rarely used directly. Instead, typically used as part of a [DatePicker].
   MonthPicker({
     Key key,
-    this.selectedDate,
-    this.onChanged,
-    this.firstDate,
-    this.lastDate
+    @required this.selectedDate,
+    @required this.onChanged,
+    @required this.firstDate,
+    @required this.lastDate
   }) : super(key: key) {
     assert(selectedDate != null);
     assert(onChanged != null);
@@ -515,10 +516,10 @@
   /// Rarely used directly. Instead, typically used as part of a [DatePicker].
   YearPicker({
     Key key,
-    this.selectedDate,
-    this.onChanged,
-    this.firstDate,
-    this.lastDate
+    @required this.selectedDate,
+    @required this.onChanged,
+    @required this.firstDate,
+    @required this.lastDate
   }) : super(key: key) {
     assert(selectedDate != null);
     assert(onChanged != null);
diff --git a/packages/flutter/lib/src/material/drop_down.dart b/packages/flutter/lib/src/material/drop_down.dart
index c3e47f3..933193c 100644
--- a/packages/flutter/lib/src/material/drop_down.dart
+++ b/packages/flutter/lib/src/material/drop_down.dart
@@ -6,6 +6,7 @@
 import 'dart:math' as math;
 
 import 'package:flutter/widgets.dart';
+import 'package:meta/meta.dart';
 
 import 'debug.dart';
 import 'icon.dart';
@@ -376,9 +377,9 @@
   /// defaults, so do not need to be specified).
   DropDownButton({
     Key key,
-    this.items,
-    this.value,
-    this.onChanged,
+    @required this.items,
+    @required this.value,
+    @required this.onChanged,
     this.elevation: 8,
     this.style,
     this.iconSize: 36.0
diff --git a/packages/flutter/lib/src/material/flat_button.dart b/packages/flutter/lib/src/material/flat_button.dart
index c6528b7..18a0d3d 100644
--- a/packages/flutter/lib/src/material/flat_button.dart
+++ b/packages/flutter/lib/src/material/flat_button.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'package:flutter/widgets.dart';
+import 'package:meta/meta.dart';
 
 import 'button.dart';
 import 'theme.dart';
@@ -40,7 +41,7 @@
   /// caps.
   FlatButton({
     Key key,
-    this.onPressed,
+    @required this.onPressed,
     this.textColor,
     this.disabledTextColor,
     this.color,
diff --git a/packages/flutter/lib/src/material/floating_action_button.dart b/packages/flutter/lib/src/material/floating_action_button.dart
index df791fc..a14461b 100644
--- a/packages/flutter/lib/src/material/floating_action_button.dart
+++ b/packages/flutter/lib/src/material/floating_action_button.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'package:flutter/widgets.dart';
+import 'package:meta/meta.dart';
 
 import 'colors.dart';
 import 'icon_theme_data.dart';
@@ -49,7 +50,7 @@
     this.backgroundColor,
     this.elevation: 6,
     this.highlightElevation: 12,
-    this.onPressed,
+    @required this.onPressed,
     this.mini: false
   }) : super(key: key);
 
diff --git a/packages/flutter/lib/src/material/icon_button.dart b/packages/flutter/lib/src/material/icon_button.dart
index a07d6c1..ab283cd 100644
--- a/packages/flutter/lib/src/material/icon_button.dart
+++ b/packages/flutter/lib/src/material/icon_button.dart
@@ -50,7 +50,7 @@
     @required this.icon,
     this.color,
     this.disabledColor,
-    this.onPressed,
+    @required this.onPressed,
     this.tooltip
   }) : super(key: key);
 
diff --git a/packages/flutter/lib/src/material/radio.dart b/packages/flutter/lib/src/material/radio.dart
index 3adf64e..1bb8143 100644
--- a/packages/flutter/lib/src/material/radio.dart
+++ b/packages/flutter/lib/src/material/radio.dart
@@ -4,6 +4,7 @@
 
 import 'package:flutter/rendering.dart';
 import 'package:flutter/widgets.dart';
+import 'package:meta/meta.dart';
 
 import 'constants.dart';
 import 'debug.dart';
@@ -47,10 +48,10 @@
   /// * [onChanged] is when the user selects this radio button.
   Radio({
     Key key,
-    this.value,
-    this.groupValue,
-    this.activeColor,
-    this.onChanged
+    @required this.value,
+    @required this.groupValue,
+    @required this.onChanged,
+    this.activeColor
   }) : super(key: key);
 
   /// The value represented by this radio button.
@@ -62,11 +63,6 @@
   /// [groupValue].
   final T groupValue;
 
-  /// The color to use when this radio button is selected.
-  ///
-  /// Defaults to accent color of the current [Theme].
-  final Color activeColor;
-
   /// Called when the user selects this radio button.
   ///
   /// The radio button passes [value] as a parameter to this callback. The radio
@@ -76,6 +72,11 @@
   /// If null, the radio button will be displayed as disabled.
   final ValueChanged<T> onChanged;
 
+  /// The color to use when this radio button is selected.
+  ///
+  /// Defaults to accent color of the current [Theme].
+  final Color activeColor;
+
   bool get _enabled => onChanged != null;
 
   Color _getInactiveColor(ThemeData themeData) {
diff --git a/packages/flutter/lib/src/material/raised_button.dart b/packages/flutter/lib/src/material/raised_button.dart
index f6e24a3..df7e24e 100644
--- a/packages/flutter/lib/src/material/raised_button.dart
+++ b/packages/flutter/lib/src/material/raised_button.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'package:flutter/widgets.dart';
+import 'package:meta/meta.dart';
 
 import 'button.dart';
 import 'colors.dart';
@@ -38,7 +39,7 @@
   /// caps.
   RaisedButton({
     Key key,
-    this.onPressed,
+    @required this.onPressed,
     this.color,
     this.disabledColor,
     this.elevation: 2,
diff --git a/packages/flutter/lib/src/material/slider.dart b/packages/flutter/lib/src/material/slider.dart
index f474a31..ba72f23 100644
--- a/packages/flutter/lib/src/material/slider.dart
+++ b/packages/flutter/lib/src/material/slider.dart
@@ -7,6 +7,7 @@
 import 'package:flutter/gestures.dart';
 import 'package:flutter/rendering.dart';
 import 'package:flutter/widgets.dart';
+import 'package:meta/meta.dart';
 
 import 'colors.dart';
 import 'constants.dart';
@@ -50,13 +51,13 @@
   /// * [onChanged] is called when the user selects a new value for the slider.
   Slider({
     Key key,
-    this.value,
+    @required this.value,
+    @required this.onChanged,
     this.min: 0.0,
     this.max: 1.0,
     this.divisions,
     this.label,
-    this.activeColor,
-    this.onChanged
+    this.activeColor
   }) : super(key: key) {
     assert(value != null);
     assert(min != null);
@@ -70,6 +71,15 @@
   /// The slider's thumb is drawn at a position that corresponds to this value.
   final double value;
 
+  /// Called when the user selects a new value for the slider.
+  ///
+  /// The slider passes the new value to the callback but does not actually
+  /// change state until the parent widget rebuilds the slider with the new
+  /// value.
+  ///
+  /// If null, the slider will be displayed as disabled.
+  final ValueChanged<double> onChanged;
+
   /// The minium value the user can select.
   ///
   /// Defaults to 0.0.
@@ -97,15 +107,6 @@
   /// Defaults to accent color of the current [Theme].
   final Color activeColor;
 
-  /// Called when the user selects a new value for the slider.
-  ///
-  /// The slider passes the new value to the callback but does not actually
-  /// change state until the parent widget rebuilds the slider with the new
-  /// value.
-  ///
-  /// If null, the slider will be displayed as disabled.
-  final ValueChanged<double> onChanged;
-
   void _handleChanged(double value) {
     assert(onChanged != null);
     onChanged(value * (max - min) + min);
diff --git a/packages/flutter/lib/src/material/snack_bar.dart b/packages/flutter/lib/src/material/snack_bar.dart
index e0a0b33..646dec8 100644
--- a/packages/flutter/lib/src/material/snack_bar.dart
+++ b/packages/flutter/lib/src/material/snack_bar.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'package:flutter/widgets.dart';
+import 'package:meta/meta.dart';
 
 import 'button.dart';
 import 'flat_button.dart';
@@ -46,7 +47,11 @@
   /// Creates an action for a [SnackBar].
   ///
   /// The [label] and [onPressed] arguments must be non-null.
-  SnackBarAction({Key key, this.label, this.onPressed }) : super(key: key) {
+  SnackBarAction({
+    Key key,
+    this.label,
+    @required this.onPressed
+  }) : super(key: key) {
     assert(label != null);
     assert(onPressed != null);
   }
diff --git a/packages/flutter/lib/src/material/switch.dart b/packages/flutter/lib/src/material/switch.dart
index f2db893..3b5ee8a 100644
--- a/packages/flutter/lib/src/material/switch.dart
+++ b/packages/flutter/lib/src/material/switch.dart
@@ -5,6 +5,7 @@
 import 'package:flutter/gestures.dart';
 import 'package:flutter/rendering.dart';
 import 'package:flutter/widgets.dart';
+import 'package:meta/meta.dart';
 
 import 'colors.dart';
 import 'constants.dart';
@@ -42,16 +43,25 @@
   /// * [onChanged] is called when the user toggles with switch on or off.
   Switch({
     Key key,
-    this.value,
+    @required this.value,
+    @required this.onChanged,
     this.activeColor,
     this.activeThumbDecoration,
-    this.inactiveThumbDecoration,
-    this.onChanged
+    this.inactiveThumbDecoration
   }) : super(key: key);
 
   /// Whether this switch is on or off.
   final bool value;
 
+  /// Called when the user toggles with switch on or off.
+  ///
+  /// The switch passes the new value to the callback but does not actually
+  /// change state until the parent widget rebuilds the switch with the new
+  /// value.
+  ///
+  /// If null, the switch will be displayed as disabled.
+  final ValueChanged<bool> onChanged;
+
   /// The color to use when this switch is on.
   ///
   /// Defaults to accent color of the current [Theme].
@@ -67,15 +77,6 @@
   /// Defaults to a circular piece of material.
   final Decoration inactiveThumbDecoration;
 
-  /// Called when the user toggles with switch on or off.
-  ///
-  /// The switch passes the new value to the callback but does not actually
-  /// change state until the parent widget rebuilds the switch with the new
-  /// value.
-  ///
-  /// If null, the switch will be displayed as disabled.
-  final ValueChanged<bool> onChanged;
-
   @override
   Widget build(BuildContext context) {
     assert(debugCheckHasMaterial(context));
diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart
index 7eb1719..56a5bf6 100644
--- a/packages/flutter/lib/src/material/tabs.dart
+++ b/packages/flutter/lib/src/material/tabs.dart
@@ -8,6 +8,7 @@
 import 'package:flutter/physics.dart';
 import 'package:flutter/rendering.dart';
 import 'package:flutter/widgets.dart';
+import 'package:meta/meta.dart';
 
 import 'colors.dart';
 import 'debug.dart';
@@ -455,9 +456,9 @@
   TabBarSelection({
     Key key,
     this.value,
-    this.values,
+    @required this.values,
     this.onChanged,
-    this.child
+    @required this.child
   }) : super(key: key)  {
     assert(values != null && values.length > 0);
     assert(new Set<T>.from(values).length == values.length);
diff --git a/packages/flutter/lib/src/material/time_picker.dart b/packages/flutter/lib/src/material/time_picker.dart
index db6536b..3f42dde 100644
--- a/packages/flutter/lib/src/material/time_picker.dart
+++ b/packages/flutter/lib/src/material/time_picker.dart
@@ -6,6 +6,7 @@
 
 import 'package:flutter/services.dart';
 import 'package:flutter/widgets.dart';
+import 'package:meta/meta.dart';
 
 import 'colors.dart';
 import 'theme.dart';
@@ -119,8 +120,8 @@
   /// creates a time picker dialog.
   TimePicker({
     Key key,
-    this.selectedTime,
-    this.onChanged
+    @required this.selectedTime,
+    @required this.onChanged
   }) : super(key: key) {
     assert(selectedTime != null);
   }
@@ -180,10 +181,10 @@
 // TODO(ianh): Localize!
 class _TimePickerHeader extends StatelessWidget {
   _TimePickerHeader({
-    this.selectedTime,
-    this.mode,
-    this.onModeChanged,
-    this.onChanged
+    @required this.selectedTime,
+    @required this.mode,
+    @required this.onModeChanged,
+    @required this.onChanged
   }) {
     assert(selectedTime != null);
     assert(mode != null);
@@ -393,9 +394,9 @@
 
 class _Dial extends StatefulWidget {
   _Dial({
-    this.selectedTime,
-    this.mode,
-    this.onChanged
+    @required this.selectedTime,
+    @required this.mode,
+    @required this.onChanged
   }) {
     assert(selectedTime != null);
   }
diff --git a/packages/flutter/test/material/switch_test.dart b/packages/flutter/test/material/switch_test.dart
index 50677de..ad11b09 100644
--- a/packages/flutter/test/material/switch_test.dart
+++ b/packages/flutter/test/material/switch_test.dart
@@ -65,6 +65,7 @@
         child: new Center(
           child: new Switch(
             value: false,
+            onChanged: null,
             activeThumbDecoration: activeDecoration,
             inactiveThumbDecoration: inactiveDecoration
           )
diff --git a/packages/flutter/test/material/tabs_test.dart b/packages/flutter/test/material/tabs_test.dart
index d7cd511..2aeb7fe 100644
--- a/packages/flutter/test/material/tabs_test.dart
+++ b/packages/flutter/test/material/tabs_test.dart
@@ -31,6 +31,7 @@
     child: new TabBarSelection<String>(
       value: value,
       values: tabs,
+      onChanged: null,
       child: new TabBar<String>(
         key: tabBarKey,
         labels: new Map<String, TabLabel>.fromIterable(tabs, value: (String tab) => new TabLabel(text: tab)),