I am following along with an online course yet my code throws an error where the instructor's code doesn't. Yes, I've scanned over it to make sure they are identical.
Maybe there is some small detail I've missed. At any rate, can someone please help me fix this error so I can move on?
Here is the get method:
List<Map<String, Object>> get groupedTransactionValues {
return List.generate(7, (index) {
final weekDay = DateTime.now().subtract(
Duration(days: index),
);
var totalSum = 0.0;
for (int i; i < recentTransactions.length; i++) {
if (recentTransactions[i].date.day == weekDay.day &&
recentTransactions[i].date.month == weekDay.month &&
recentTransactions[i].date.year == weekDay.year) {
totalSum += recentTransactions[i].amount;
}
}
return {
'day': DateFormat.E().format(weekDay).substring(0, 1),
'amount': totalSum,
};
});
}
And here is the implementation of it in Flutter:
#override
Widget build(BuildContext context) {
return Card(
elevation: 6,
margin: EdgeInsets.all(20),
child: Row(
children: groupedTransactionValues.map((data) {
}).toList(),
),
);
}
}
And here's the error message:
The following NoSuchMethodError was thrown building Chart(dirty):
The method '<' was called on null.
Receiver: null
Tried calling: <(0)
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1 Chart.groupedTransactionValues.<anonymous closure>
package:expense/widgets/chart.dart:19
#2 new List.generate (dart:core-patch/array_patch.dart:78:28)
#3 Chart.groupedTransactionValues
package:expense/widgets/chart.dart:13
#4 Chart.build
package:expense/widgets/chart.dart:45
#5 StatelessElement.build
package:flutter/…/widgets/framework.dart:4620
#6 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4546
#7 Element.rebuild
package:flutter/…/widgets/framework.dart:4262
#8 ComponentElement._firstBuild
package:flutter/…/widgets/framework.dart:4525
#9 ComponentElement.mount
package:flutter/…/widgets/framework.dart:4520
#10 Element.inflateWidget
package:flutter/…/widgets/framework.dart:3490
#11 MultiChildRenderObjectElement.mount
package:flutter/…/widgets/framework.dart:5991
... Normal element mounting (109 frames)
#120 Element.inflateWidget
package:flutter/…/widgets/framework.dart:3490
#121 MultiChildRenderObjectElement.mount
package:flutter/…/widgets/framework.dart:5991
... Normal element mounting (210 frames)
#331 Element.inflateWidget
package:flutter/…/widgets/framework.dart:3490
#332 MultiChildRenderObjectElement.mount
package:flutter/…/widgets/framework.dart:5991
... Normal element mounting (273 frames)
#605 Element.inflateWidget
package:flutter/…/widgets/framework.dart:3490
#606 Element.updateChild
package:flutter/…/widgets/framework.dart:3258
#607 RenderObjectToWidgetElement._rebuild
package:flutter/…/widgets/binding.dart:1174
#608 RenderObjectToWidgetElement.mount
package:flutter/…/widgets/binding.dart:1145
#609 RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure>
package:flutter/…/widgets/binding.dart:1087
#610 BuildOwner.buildScope
package:flutter/…/widgets/framework.dart:2620
#611 RenderObjectToWidgetAdapter.attachToRenderTree
package:flutter/…/widgets/binding.dart:1086
#612 WidgetsBinding.attachRootWidget
package:flutter/…/widgets/binding.dart:927
#613 WidgetsBinding.scheduleAttachRootWidget.<anonymous closure>
package:flutter/…/widgets/binding.dart:908
(elided 11 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)
for (int i; i < recentTransactions.length; i++) {
This is the part causing the Error, since it is stated: "The method '<' was called on null." You have to initalise your int i = 0, so the code should look like
for (int i = 0; i < recentTransactions.length; i++) {
Related
I have read similar answers for this type of error but still, I am not able to resolve it in my code.
When I tap the button it shows an error screen for some time and then displays loader which should be displayed while the data is being fetched.
error screen
loading screen
final screen
here is the code:
import 'package:flutter/material.dart';
import 'Dictionary.dart';
import 'Services.dart';
class NewTab extends StatefulWidget {
#override
_NewTabState createState() => _NewTabState();
}
class _NewTabState extends State<NewTab> {
List<Dictionary> _users;
int len;
#override
void initState() {
super.initState();
Services.getUsers().then((users) {
setState(() {
_users = users;
len = users.length - 1 ;
});
});
}
#override
Widget build(BuildContext context) {
Dictionary user = _users[len];
print(user);
return FutureBuilder(
future: Services.getUsers(),
builder: (context,AsyncSnapshot<List<Dictionary>> snapshot){
if(snapshot.data==null){
return Center(child: CircularProgressIndicator());
}else{
return DefaultTabController(length: 2,
child:Scaffold(
appBar: AppBar(
title : Text('Meaning',
style: TextStyle(
fontFamily: "Pangolin",
fontSize: 35,
)
),
centerTitle: true,
bottom: TabBar(
tabs: <Widget>[
Tab(text:'Meaning',
icon: Icon(Icons.book_outlined),
),
Tab(text:'Example',
icon: Icon(Icons.directions_transit)
),
],
),
),
body : TabBarView(
children: <Widget>[
Container(
color: Colors.white,
child: Container(
color: Colors.black,
child: ListView.builder(
itemCount: user.meanings.length,
itemBuilder: (context, index) {
print(index);
List<Meaning> mean = user.meanings;
return ListTile(
title: Text(mean[index].definitions[0].definition
, style: TextStyle(
color: Colors.white,
),
),
);
},
),
),),Container(
child: Text('home'),
),]
)
)
);
}
},
);
}
}
code for onpressed function in raised button
onPressed: ()=>{
Navigator.of(context).push(
new MaterialPageRoute(builder: (BuildContext context) => NewTab())
)
},
code for services.dart
import 'package:http/http.dart' as http;
import 'Dictionary.dart';
import 'package:dictionary_app/home.dart';
import 'dart:async';
class Services {
static final url = 'https://api.dictionaryapi.dev/api/v2/entries/en_US/$word';
static Future<List<Dictionary>> getUsers() async {
try {
print(url);
final response = await http.get(Uri.parse(url));
print(response.statusCode);
if (200 == response.statusCode) {
final List<Dictionary> users = dictionaryFromJson(response.body);
return users;
}
else {
return <Dictionary>[];
}
} catch (e) {
return <Dictionary>[];
}
}
}
error:
The following NoSuchMethodError was thrown building NewTab(dirty, state: _NewTabState#1662b):
The method '[]' was called on null.
Receiver: null
Tried calling: [](null)
The relevant error-causing widget was:
NewTab file:///E:/Flutter-Projects/flutter3/dictionary_app/lib/home.dart:120:74
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:63:5)
#1 _NewTabState.build (package:dictionary_app/newtab.dart:25:30)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:4749:27)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4632:15)
#4 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4805:11)
#5 Element.rebuild (package:flutter/src/widgets/framework.dart:4322:5)
#6 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4610:5)
#7 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4796:11)
#8 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4605:5)
... Normal element mounting (166 frames)
#174 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3662:14)
#175 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6285:36)
#176 Element.updateChild (package:flutter/src/widgets/framework.dart:3414:18)
#177 RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:5717:32)
#178 MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6308:17)
#179 Element.updateChild (package:flutter/src/widgets/framework.dart:3401:15)
#180 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4657:16)
#181 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4805:11)
#182 Element.rebuild (package:flutter/src/widgets/framework.dart:4322:5)
#183 StatefulElement.update (package:flutter/src/widgets/framework.dart:4837:5)
#184 Element.updateChild (package:flutter/src/widgets/framework.dart:3401:15)
#185 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4657:16)
#186 Element.rebuild (package:flutter/src/widgets/framework.dart:4322:5)
#187 ProxyElement.update (package:flutter/src/widgets/framework.dart:4985:5)
#188 Element.updateChild (package:flutter/src/widgets/framework.dart:3401:15)
#189 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4657:16)
#190 Element.rebuild (package:flutter/src/widgets/framework.dart:4322:5)
#191 ProxyElement.update (package:flutter/src/widgets/framework.dart:4985:5)
#192 _InheritedNotifierElement.update (package:flutter/src/widgets/inherited_notifier.dart:181:11)
#193 Element.updateChild (package:flutter/src/widgets/framework.dart:3401:15)
#194 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6154:14)
#195 Element.updateChild (package:flutter/src/widgets/framework.dart:3401:15)
#196 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4657:16)
#197 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4805:11)
#198 Element.rebuild (package:flutter/src/widgets/framework.dart:4322:5)
#199 StatefulElement.update (package:flutter/src/widgets/framework.dart:4837:5)
#200 Element.updateChild (package:flutter/src/widgets/framework.dart:3401:15)
#201 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6154:14)
#202 Element.updateChild (package:flutter/src/widgets/framework.dart:3401:15)
#203 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6154:14)
#204 Element.updateChild (package:flutter/src/widgets/framework.dart:3401:15)
#205 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4657:16)
#206 Element.rebuild (package:flutter/src/widgets/framework.dart:4322:5)
#207 ProxyElement.update (package:flutter/src/widgets/framework.dart:4985:5)
#208 Element.updateChild (package:flutter/src/widgets/framework.dart:3401:15)
#209 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4657:16)
#210 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4805:11)
#211 Element.rebuild (package:flutter/src/widgets/framework.dart:4322:5)
#212 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2619:33)
#213 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:878:21)
#214 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:328:5)
#215 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1147:15)
#216 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1084:9)
#217 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1000:5)
#221 _invoke (dart:ui/hooks.dart:163:10)
#222 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:259:5)
#223 _drawFrame (dart:ui/hooks.dart:126:31)
(elided 3 frames from dart:async)
First of all you can remove your initState method since you are already using the FutureBuilder to fetch your Services.getUsers().
Now, you have defined your variables like this,
List<Dictionary> _users;
int len;
But both of them are null when build method is going to be called for the first time.
So inside your build method, you can't directly use,
Dictionary user = _users[len];
print(user);
Since, _users is null when build is called for the first time. So remove those 2 lines.
Now, rest of your code is correct, except for one part,
Inside your else case of if(snapshot.data==null), define your user variable like this,
else {
Dictionary user = snapshot.data!.last; // This gives you the last element of the array
Now, your code should work.
Here is the paste bin link for the full code of _NewTabState.
You have to initialize your list
List<Dictionary> _users = [];
It’s better way:
snapShot.connectionState == ConnectionState.waiting ? :
I am trying to test my submit button which fires a bloc event onPress.
SubmitButton.dart - Widget
class AuthenticationSubmitButton extends StatefulWidget {
final String buttonLabel;
final TextEditingController _userEmailController;
final TextEditingController _passwordController;
AuthenticationSubmitButton(
this.buttonLabel, this._userEmailController, this._passwordController);
#override
_AuthenticationSubmitButtonState createState() =>
_AuthenticationSubmitButtonState();
}
class _AuthenticationSubmitButtonState
extends State<AuthenticationSubmitButton> {
#override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size;
final _authBloc = BlocProvider.of<AuthenticationBloc>(context);
return Container(
child: FlatButton.icon(
height: screenSize.height * 0.07,
minWidth: screenSize.width * 0.5,
padding: EdgeInsets.all(10),
color: Colors.green,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
onPressed: () {
final email = widget._userEmailController.text.trim();
final password = widget._passwordController.text.trim();
_authBloc.add(UserLoginEvent(email, password));
},
icon: Icon(Icons.keyboard_return_rounded),
label: Text(
widget.buttonLabel,
style: SubmitButtonStyle,
),
),
);
}
}
As you can see I am calling the event UserLoginEvent
authentication_events.dart
#immutable
abstract class AuthenticationEvent {}
/**
* Login Event
* Logout Event
*/
class UserLoginEvent extends AuthenticationEvent {
final String userEmail;
final String userPassword;
UserLoginEvent(this.userEmail, this.userPassword);
}
class ClearLoginEvent extends AuthenticationEvent {
}
And here is my authentication states
authentication_states.dart
#immutable
abstract class AuthenticationState extends Equatable {
}
class AuthenticationInitial extends AuthenticationState {
#override
List<Object> get props => [];
}
/**
* LoginSuccessful
* LoginFailed
* LogoutSuccessful
*/
class LoginSuccessful extends AuthenticationState {
#override
List<Object> get props => [];
}
class LoginError extends AuthenticationState {
#override
List<Object> get props => [];
}
authentication_bloc.dart
class AuthenticationBloc
extends Bloc<AuthenticationEvent, AuthenticationState> {
AuthenticationBloc({this.userRepository}) : super(AuthenticationInitial());
UserRepository userRepository;
#override
Stream<AuthenticationState> mapEventToState(
AuthenticationEvent event,
) async* {
if (event is UserLoginEvent) {
UserRepository repository = userRepository ?? UserRepository();
try {
bool loggedIn = await repository.authenticateUserWithCredentials(
event.userEmail, event.userPassword);
if (loggedIn) {
yield LoginSuccessful();
} else {
yield LoginError();
}
} catch (e) {
yield EmptyLoginCredentials();
}
} else if (event is ClearLoginEvent) {
yield AuthenticationInitial();
}
}
}
And finally my test for submit button
> submit_button_test.dart
class MockAuthBloc extends MockBloc<AuthenticationState>
implements AuthenticationBloc {}
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
MockAuthBloc authBloc = MockAuthBloc();
TextEditingController _userEmailController;
TextEditingController _passwordController;
setUp(() {
_userEmailController = TextEditingController();
_passwordController = TextEditingController();
authBloc = MockAuthBloc();
});
tearDown(() {
_userEmailController.dispose();
_passwordController.dispose();
authBloc?.close();
});
///Provide Material App for giving access to MediaQuery
///Wrap any widget that needs Material widget
Widget buildTestableWidget(Widget widget) {
return MediaQuery(
data: MediaQueryData(),
child: BlocProvider.value(
value: authBloc,
child: MaterialApp(
home: Material(
child: widget,
),
),
),
);
}
group('Testing Submit button |', () {
testWidgets('description', (WidgetTester tester) async {
whenListen(
authBloc,
Stream.fromIterable(<AuthenticationState>[LoginSuccessful()]),
);
await tester.pumpWidget(buildTestableWidget(AuthenticationSubmitButton(
'Submit', _userEmailController, _passwordController)));
final buttonFinder = find.byType(FlatButton);
final button = tester.firstWidget(buttonFinder);
});
});
}
Could you please tell me what am I doing wrong here?
Below is my error
00:03 +19: /home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart: Testing Submit button | description
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building AuthenticationSubmitButton(dirty, dependencies:
[MediaQuery], state: _AuthenticationSubmitButtonState#da4f9):
BlocProvider.of() called with a context that does not contain a Bloc/Cubit of type
AuthenticationBloc.
No ancestor could be found starting from the context that was passed to
BlocProvider.of<AuthenticationBloc>().
This can happen if the context you used comes from a widget above the BlocProvider.
The context used was: AuthenticationSubmitButton(dirty, dependencies: [MediaQuery], state:
_AuthenticationSubmitButtonState#da4f9)
The relevant error-causing widget was:
AuthenticationSubmitButton
file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart:57:51
When the exception was thrown, this was the stack:
#0 BlocProvider.of (package:flutter_bloc/src/bloc_provider.dart:121:7)
#1 _AuthenticationSubmitButtonState.build (package:kaadhal_host_client/screens/Authentication/widgets/submit_button.dart:26:36)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:4744:28)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4627:15)
#4 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4800:11)
#5 Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5)
#6 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4606:5)
#7 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4791:11)
#8 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4601:5)
... Normal element mounting (174 frames)
#182 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
#183 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
... Normal element mounting (267 frames)
#450 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
#451 Element.updateChild (package:flutter/src/widgets/framework.dart:3327:18)
#452 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4652:16)
#453 _InheritedProviderScopeElement.performRebuild (package:provider/src/inherited_provider.dart:426:11)
#454 Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5)
#455 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4606:5)
#456 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4601:5)
... Normal element mounting (7 frames)
#463 SingleChildWidgetElementMixin.mount (package:nested/nested.dart:223:11)
... Normal element mounting (7 frames)
#470 SingleChildWidgetElementMixin.mount (package:nested/nested.dart:223:11)
... Normal element mounting (7 frames)
#477 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
#478 Element.updateChild (package:flutter/src/widgets/framework.dart:3324:20)
#479 RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1252:16)
#480 RenderObjectToWidgetElement.update (package:flutter/src/widgets/binding.dart:1230:5)
#481 RenderObjectToWidgetElement.performRebuild (package:flutter/src/widgets/binding.dart:1244:7)
#482 Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5)
#483 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2730:33)
#484 AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1088:18)
#485 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:302:5)
#486 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1117:15)
#487 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1055:9)
#488 AutomatedTestWidgetsFlutterBinding.pump.<anonymous closure> (package:flutter_test/src/binding.dart:961:9)
#491 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:72:41)
#492 AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:948:27)
#493 WidgetTester.pumpWidget.<anonymous closure> (package:flutter_test/src/widget_tester.dart:524:22)
#496 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:72:41)
#497 WidgetTester.pumpWidget (package:flutter_test/src/widget_tester.dart:521:27)
#498 main.<anonymous closure>.<anonymous closure> (file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart:57:20)
#499 main.<anonymous closure>.<anonymous closure> (file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart:46:32)
#500 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:146:29)
#511 FakeAsync.flushMicrotasks (package:fake_async/fake_async.dart:193:32)
#512 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1189:17)
#513 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1177:35)
(elided 29 frames from dart:async and package:stack_trace)
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following StateError was thrown running a test:
Bad state: No element
When the exception was thrown, this was the stack:
#0 Iterable.first (dart:core/iterable.dart:524:7)
#1 WidgetController.firstWidget (package:flutter_test/src/controller.dart:79:30)
#2 main.<anonymous closure>.<anonymous closure> (file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart:60:29)
<asynchronous suspension>
#3 main.<anonymous closure>.<anonymous closure> (file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart)
#4 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:146:29)
<asynchronous suspension>
#5 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart)
#6 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:784:19)
<asynchronous suspension>
#9 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:764:14)
#10 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1173:24)
#11 FakeAsync.run.<anonymous closure>.<anonymous closure> (package:fake_async/fake_async.dart:178:54)
#16 withClock (package:clock/src/default.dart:48:10)
#17 FakeAsync.run.<anonymous closure> (package:fake_async/fake_async.dart:178:22)
#22 FakeAsync.run (package:fake_async/fake_async.dart:178:7)
#23 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1170:15)
#24 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:138:24)
#25 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:175:19)
<asynchronous suspension>
#26 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart)
#31 Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:173:13)
#32 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:231:15)
#37 Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:228:5)
#38 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:383:17)
<asynchronous suspension>
#39 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart)
#44 Invoker._onRun.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:370:9)
#45 Invoker._guardIfGuarded (package:test_api/src/backend/invoker.dart:415:15)
#46 Invoker._onRun.<anonymous closure> (package:test_api/src/backend/invoker.dart:369:7)
#53 Invoker._onRun (package:test_api/src/backend/invoker.dart:368:11)
#54 LiveTestController.run (package:test_api/src/backend/live_test_controller.dart:153:11)
#55 RemoteListener._runLiveTest.<anonymous closure> (package:test_api/src/remote_listener.dart:256:16)
#60 RemoteListener._runLiveTest (package:test_api/src/remote_listener.dart:255:5)
#61 RemoteListener._serializeTest.<anonymous closure> (package:test_api/src/remote_listener.dart:208:7)
#79 _GuaranteeSink.add (package:stream_channel/src/guarantee_channel.dart:125:12)
#80 new _MultiChannel.<anonymous closure> (package:stream_channel/src/multi_channel.dart:159:31)
#84 CastStreamSubscription._onData (dart:_internal/async_cast.dart:85:11)
#118 new _WebSocketImpl._fromSocket.<anonymous closure> (dart:_http/websocket_impl.dart:1145:21)
#126 _WebSocketProtocolTransformer._messageFrameEnd (dart:_http/websocket_impl.dart:338:23)
#127 _WebSocketProtocolTransformer.add (dart:_http/websocket_impl.dart:232:46)
#137 _Socket._onData (dart:io-patch/socket_patch.dart:2044:41)
#146 new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1580:33)
#147 _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1076:14)
(elided 111 frames from dart:async and package:stack_trace)
The test description was:
description
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following message was thrown:
Multiple exceptions (2) were detected during the running of the current test, and at least one was
unexpected.
════════════════════════════════════════════════════════════════════════════════════════════════════
00:03 +19 -1: /home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart: Testing Submit button | description [E]
Test failed. See exception logs above.
The test description was: description
Reasons-
You are coming on this class thought navigator
Your parent is not using same bloc
Solution-
You can use bloc here by passing it to constructor
My question is pretty straightforward, I think, but I haven't been able to find an answer anywhere. I am passing an ImageProvider to my PixelData class to be able to access individual pixel color values, but I need to get the ui.Image and the image byte data out of the ImageProvider. I'm running into the issue shown below where I can't access those values without using createLocalImageConfiguration(buildContext) with the current BuildContext. I would like to be able to use this class outside of the BuildContext scope and so I need to be able to get the image data without the BuildContext.
I would really appreciate any help/guidance with this problem.
Thank you!
class PixelData {
ImageProvider imageProvider;
ui.Image _image;
ByteData _byteData;
int _width;
int _height;
PixelData(this.imageProvider) : assert(imageProvider != null);
int get width => _width;
int get height => _height;
Future<void> getByteData() async {
if (imageProvider == null) throw Exception("imageProvider is null");
// TODO here lies the problem.
// TODO how can I provide an ImageConfiguration without BuildContext?
// I can't use: createLocalImageConfiguration(buildContext)
imageProvider.resolve(configuration).addListener(
ImageStreamListener(
(info, _) async {
_image = info.image;
_width = _image.width;
_height = _image.height;
_byteData =
await _image.toByteData(format: ui.ImageByteFormat.rawRgba);
},
),
);
}
void getColorAt() {
// TODO
}
}
I tried using ImageConfiguration.empty, which is recommended when the context isn't available.
Here is the relevant updated code and the error that came after trying to run it.
/// getByteData must be called before trying to access pixel data
Future<void> getByteData() async {
if (imageProvider == null) throw Exception("imageProvider is null");
imageProvider.resolve(ImageConfiguration.empty).addListener(
ImageStreamListener(
(info, _) async {
print("code reached");
_image = info.image;
_width = _image.width;
_height = _image.height;
_byteData =
await _image.toByteData(format: ui.ImageByteFormat.rawRgba);
},
),
);
}
/// Pixel coordinates: (0,0) → (width-1, height-1).
Color pixelColorAt(int x, int y) {
if (_byteData == null ||
width == null ||
height == null ||
x < 0 ||
x >= width ||
y < 0 ||
y >= height)
return null;
else {
var byteOffset = 4 * (x + (y * width));
return _colorAtByteOffset(byteOffset);
}
}
test('test network image', () async {
String url =
"https://i0.wp.com/www.dignited.com/wp-content/uploads/2012/09/Magazine-QR-Code.jpg?fit=500%2C404&ssl=1";
final PixelData pixelData = PixelData(imageProvider: NetworkImage(url));
await pixelData.getByteData();
Color a = pixelData.pixelColorAt(282, 287);
Color b = pixelData.pixelColorAt(218, 105);
Color c = pixelData.pixelColorAt(160, 93);
Color d = pixelData.pixelColorAt(-1, 100);
print(a.value);
print(b.value);
print(c.value);
expect(d, null);
});
══╡ EXCEPTION CAUGHT BY IMAGE RESOURCE SERVICE ╞════════════════════════════════════════════════════
The following _CastError was thrown while resolving an image:
Null check operator used on a null value
When the exception was thrown, this was the stack:
#0 ImageProvider.resolveStreamForKey (package:flutter/src/painting/image_provider.dart:502:69)
#1 ImageProvider.resolve.<anonymous closure> (package:flutter/src/painting/image_provider.dart:333:9)
#2 ImageProvider._createErrorHandlerAndKey.<anonymous closure>.<anonymous closure> (package:flutter/src/painting/image_provider.dart:463:26)
#3 SynchronousFuture.then (package:flutter/src/foundation/synchronous_future.dart:41:35)
#4 ImageProvider._createErrorHandlerAndKey.<anonymous closure> (package:flutter/src/painting/image_provider.dart:460:11)
#8 ImageProvider._createErrorHandlerAndKey (package:flutter/src/painting/image_provider.dart:452:16)
#9 ImageProvider.resolve (package:flutter/src/painting/image_provider.dart:330:5)
#10 PixelData.getByteData (package:pixel_data/simplifying_image_pixels.dart:26:19)
#11 main.<anonymous closure> (file:///Users/graysonharrington/Documents/Programming/Flutter/apps/pixel_data/test/pixel_data_test.dart:14:21)
#12 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:175:19)
<asynchronous suspension>
#13 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart)
#18 Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:173:13)
#19 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:231:15)
#24 Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:228:5)
#25 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:383:17)
<asynchronous suspension>
#26 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart)
#31 Invoker._onRun.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:370:9)
#32 Invoker._guardIfGuarded (package:test_api/src/backend/invoker.dart:415:15)
#33 Invoker._onRun.<anonymous closure> (package:test_api/src/backend/invoker.dart:369:7)
#40 Invoker._onRun (package:test_api/src/backend/invoker.dart:368:11)
#41 LiveTestController.run (package:test_api/src/backend/live_test_controller.dart:153:11)
#42 RemoteListener._runLiveTest.<anonymous closure> (package:test_api/src/remote_listener.dart:256:16)
#47 RemoteListener._runLiveTest (package:test_api/src/remote_listener.dart:255:5)
#48 RemoteListener._serializeTest.<anonymous closure> (package:test_api/src/remote_listener.dart:208:7)
#66 _GuaranteeSink.add (package:stream_channel/src/guarantee_channel.dart:125:12)
#67 new _MultiChannel.<anonymous closure> (package:stream_channel/src/multi_channel.dart:159:31)
#71 CastStreamSubscription._onData (dart:_internal/async_cast.dart:85:11)
#105 new _WebSocketImpl._fromSocket.<anonymous closure> (dart:_http/websocket_impl.dart:1145:21)
#113 _WebSocketProtocolTransformer._messageFrameEnd (dart:_http/websocket_impl.dart:338:23)
#114 _WebSocketProtocolTransformer.add (dart:_http/websocket_impl.dart:232:46)
#124 _Socket._onData (dart:io-patch/socket_patch.dart:2044:41)
#133 new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1580:33)
#134 _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1076:14)
(elided 104 frames from dart:async and package:stack_trace)
Image provider:
NetworkImage("https://i0.wp.com/www.dignited.com/wp-content/uploads/2012/09/Magazine-QR-Code.jpg?fit=500%2C404&ssl=1",
scale: 1.0)
Image configuration: ImageConfiguration()
Image key:
NetworkImage("https://i0.wp.com/www.dignited.com/wp-content/uploads/2012/09/Magazine-QR-Code.jpg?fit=500%2C404&ssl=1",
scale: 1.0)
════════════════════════════════════════════════════════════════════════════════════════════════════
The pixelColorAt() function has been tested previously using ui.Image objects and works as expected. I'm just trying to get the class to work with ImageProvider constructor variables rather than ui.Image.
Just look at the source code:
ImageConfiguration createLocalImageConfiguration(BuildContext context, { Size size }) {
return ImageConfiguration(
bundle: DefaultAssetBundle.of(context),
devicePixelRatio: MediaQuery.of(context, nullOk: true)?.devicePixelRatio ?? 1.0,
locale: Localizations.localeOf(context, nullOk: true),
textDirection: Directionality.of(context),
size: size,
platform: defaultTargetPlatform,
);
}
Thus, as long as you provide those things like bundle, devicePixelRatio, etc, manually, then you can happily create the ImageConfiguration.
Actually some parts can be null. For example, locale: Localizations.localeOf(context, nullOk: true) has nullOk: true. Thus you can simply write ImageConiguration(locale: null, ...). Other parts are similar.
In conclusion, write a method like:
ImageConfiguration myOwnCreateLocalImageConfigurationWithoutBuildContext() {
return ImageConfiguration(
bundle: maybenullorsomething,
devicePixelRatio: 1.0,
locale: null,
textDirection: Directionality.ltr, // or something you like
size: null,
platform: defaultTargetPlatform,
);
}
why don't just create default one?
imageProvider.resolve(const ImageConfiguration())
I am trying to test my stateful widget CheckedTextField:
class _CheckedTextFieldState extends State<CheckedTextField> {
TextEditingController _controller = TextEditingController();
bool _checked;
String _valueBackup;
#override
void initState() {
super.initState();
_checked = widget.initialChecked;
_controller.text = widget.initialValue;
_controller.addListener(invokeCallback);
}
invokeCallback() {
widget.callback(_controller.text.trim(), _checked);
}
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Expanded(
child: TextField(
enabled: _checked,
controller: _controller,
decoration: widget.decoration,
),
),
Checkbox(
onChanged: (value) {
if (value == false) {
_valueBackup = _controller.text;
_controller.text = "";
}
if (value == true) {
_controller.text = _valueBackup;
}
setState(() {
_checked = value;
});
invokeCallback();
},
value: _checked,
),
],
);
}
}
When I try to test the widget with the following code, the engine tells me to show the keyboard first:
testWidgets('enter text when not checked', (WidgetTester tester) async {
String value = "";
bool checked = false;
await tester.pumpWidget(
wrapMaterial(
CheckedTextField(
initialValue: value,
initialChecked: checked,
callback: (_value, _checked) {
value = _value;
checked = _checked;
},
),
),
);
await tester.enterText(find.byType(TextField), "newText");
expect(value, "newText");
expect(checked, isFalse);
});
I already tried to show the keyboard manually with await tester.showKeyboard(find.byType(TextField)); before entering the text, but the issue still remains.
I also wrote a finder predicate to make sure the TextField is found, so the issue seems to be somewhere else.
The thrown exception:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
Tried to use TestTextInput with no keyboard attached. You must use WidgetTester.showKeyboard() first.
When the exception was thrown, this was the stack:
#0 TestTextInput.updateEditingValue (package:flutter_test/src/test_text_input.dart:133:7)
#1 TestTextInput.enterText (package:flutter_test/src/test_text_input.dart:170:5)
#2 WidgetTester.enterText.<anonymous closure> (package:flutter_test/src/widget_tester.dart:875:21)
<asynchronous suspension>
#3 WidgetTester.enterText.<anonymous closure> (package:flutter_test/src/widget_tester.dart)
#6 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:72:41)
#7 WidgetTester.enterText (package:flutter_test/src/widget_tester.dart:873:27)
#8 main.<anonymous closure> (file:///home/kevin/Projekte/Blackout/test/widget/checked_text_field/checked_text_field_test.dart:54:18)
<asynchronous suspension>
#9 main.<anonymous closure> (file:///home/kevin/Projekte/Blackout/test/widget/checked_text_field/checked_text_field_test.dart)
#10 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:140:29)
<asynchronous suspension>
#11 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart)
#12 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:703:19)
<asynchronous suspension>
#15 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:683:14)
#16 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1083:24)
#17 FakeAsync.run.<anonymous closure>.<anonymous closure> (package:fake_async/fake_async.dart:177:54)
#22 withClock (package:clock/src/default.dart:46:10)
#23 FakeAsync.run.<anonymous closure> (package:fake_async/fake_async.dart:177:22)
#28 FakeAsync.run (package:fake_async/fake_async.dart:177:7)
#29 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1080:15)
#30 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:133:24)
#31 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:172:27)
<asynchronous suspension>
#32 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart)
#33 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:246:15)
#38 Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:243:5)
#39 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:170:33)
#44 Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:169:13)
#45 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:400:30)
(elided 36 frames from class _RawReceivePortImpl, class _Timer, dart:async, dart:async-patch, and package:stack_trace)
The test description was:
enter text when not checked
════════════════════════════════════════════════════════════════════════════════════════════════════
You need attach the textInput to it. Simply use
await tester.showKeyboard(find.byType(TextField));
testWidgets('enter text when not checked', (WidgetTester tester) async {
String value = "";
bool checked = false;
await tester.pumpWidget(
wrapMaterial(
CheckedTextField(
initialValue: value,
initialChecked: checked,
callback: (_value, _checked) {
value = _value;
checked = _checked;
},
),
),
);
await tester.showKeyboard(find.byType(TextField));
await tester.enterText(find.byType(TextField), "newText");
expect(value, "newText"); //it's not part of the question but this WILL not change
expect(checked, isFalse);
});
If you want to check state of this EditableText, ie. controller, widget properties, ...;
final _focusedEditable = tester.state<EditableTextState>(
find.descendant(
of: find.byType(TextField).first,
matching: find.byType(EditableText),
matchRoot: true,
),
);
If you want to check the text input use
tester.testTextInput, ie. keyboard visibility, clients listening
Before I update to the new version of flutter (see below) everything worked OK.
Now it does no longer work.
The following piece of code performs a "paged" load of a gridView
Could somebody tell me what has changed with the last version of Flutter and how to solve this issue ?
Many thanks
Flutter version:
flutter --version
Flutter 0.2.8 • channel beta • https://github.com/flutter/flutter.git
Framework • revision b397406561 (11 days ago) • 2018-04-02 13:53:20 -0700
Engine • revision c903c217a1
Tools • Dart 2.0.0-dev.43.0.flutter-52afcba357
Here is the code that used to work:
typedef Future<PageAnswer> ApiPageRequest(int page, int pageSize);
class MIDApi {
///
/// Returns the list of items belonging to the active profile
///
Future<PageAnswer> getItems({
int pageIndex: 0,
int pageSize: 50,
#required String sortOrder
}) async {
String url = "ItemsList/$sortOrder";
return ajaxGet(url).then((String responseBody) async {
// print(responseBody);
final Map response = json.decode(responseBody);
final _status = response["status"];
if (_status == "OK"){
// Everything is OK
Map map = json.decode(response["data"]);
List<Map> objects = map["List"];
int total = map["Total"];
return new PageAnswer(objects, total);
}
return Null;
}).catchError((){
return Null;
});
}
}
///
/// This widget is used to display a "paged" GridView
///
/// Invocation example:
/// new PagedGridView<Map>(request, widgetAdapter: adapt);
///
/// where: request could be
/// Future<List<Map>> request(int page, int pageSize) async {
/// routine to fetch the data from the server
/// }
///
/// and adapt could be:
/// Widget adapt(Map map){
/// return new MyWidget(map);
/// }
///
class PagedGridView extends StatefulWidget {
/// Abstraction for loading the data.
/// This can be anything: An API-Call,
/// loading data from a certain file or database,
/// etc. If will deliver a list of objects (of type T)
final ApiPageRequest pageRequest;
/// The number of columns per row of the grid
final int numberColumns;
/// The number of elements requested for each page
final int pageSize;
/// The number of left-over elements in list which
/// will trigger loading the next page
final int pageThreshold;
/// Used for building Widgets out of the fetched data
final WidgetAdapter<Map> widgetAdapter;
final bool reverse;
final Indexer<Map> indexer;
final Stream<Map> topStream;
/// Constructor
const PagedGridView({
Key key,
this.numberColumns: 2,
this.pageSize: 50,
this.pageThreshold: 10,
#required this.pageRequest,
#required this.widgetAdapter,
this.reverse: false,
this.indexer,
this.topStream
}): super(key: key);
#override
State<StatefulWidget> createState() {
return new PagedGridViewState();
}
}
class PagedGridViewState extends State<PagedGridView> {
/// Contains all fetched elements ready to display
List<Map> objects = [];
/// Total number of objects that could be returned
int total = -1;
/// A Future returned by loadNext() if there
/// is currently a request running
/// or null, if no request is performed
Future request;
Map<int, int> index = {};
void doSomething(){
print("I need to do something");
}
void Clear() async {
await onRefresh();
}
#override
void initState(){
super.initState();
/// At start, let's systematically try to fetch some data
this.lockedLoadNext();
if (widget.topStream != null){
widget.topStream.listen((Map t){
setState((){
this.objects.insert(0, t);
this.reIndex();
});
});
}
}
#override
Widget build(BuildContext context){
GridView listView = new GridView.builder(
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: widget.numberColumns),
itemBuilder: itemBuilder,
itemCount: objects.length,
reverse: widget.reverse
);
RefreshIndicator refreshIndicator = new RefreshIndicator(
onRefresh: onRefresh,
child: listView
);
return new NotificationListener<ListElementUpdate<Map>>(
child: refreshIndicator,
onNotification: onUpdate
);
}
Widget itemBuilder(BuildContext context, int index){
/// If we are entering the threshold zone,
/// try to fetch additional objects
if (index + widget.pageThreshold > objects.length){
notifyThreshold();
}
return widget.widgetAdapter != null ? widget.widgetAdapter(objects[index])
: new Container();
}
void notifyThreshold(){
lockedLoadNext();
}
bool onUpdate(ListElementUpdate<Map> update){
if (widget.indexer == null){
debugPrint('ListElementUpdate on un-indexed list');
return false;
}
int index = this.index[update.key];
if (index == null){
debugPrint('ListElementUpdate index not found');
return false;
}
setState((){
this.objects[index] = update.instance;
});
return true;
}
Future onRefresh() async {
this.request?.timeout(const Duration());
PageAnswer answer = await widget.pageRequest(0, widget.pageSize);
List<Map> fetched = answer.list;
total = answer.total;
setState(() {
this.objects.clear();
this.index.clear();
this.addObjects(fetched);
});
return true;
}
///
/// This routine only fetches new data, if no other request is pending
///
void lockedLoadNext() {
if (this.request == null) {
this.request = loadNext().then((x) {
this.request = null;
});
}
}
Future loadNext() async {
// If there is no need to fetch any further data, simply return
if (objects.length >= total && total != -1){
return Null;
}
int page = (objects.length / widget.pageSize).floor();
PageAnswer answer = await widget.pageRequest(page, widget.pageSize);
List<Map> fetched = answer.list;
total = answer.total;
if (mounted) {
this.setState(() {
addObjects(fetched);
});
}
}
void addObjects(Iterable<Map> objects) {
objects.forEach((Map object) {
int index = this.objects.length;
this.objects.add(object);
if (widget.indexer != null) {
this.index[widget.indexer(object)] = index;
}
});
}
void reIndex(){
this.index .clear();
if (widget.indexer!=null){
int i = 0;
this.objects.forEach((object){
index[widget.indexer(object)] == i;
i++;
});
}
}
}
Invocation code:
class ItemsPage extends StatefulWidget {
#override
_ItemsPageState createState() => new _ItemsPageState();
}
class _ItemsPageState extends State<ItemsPage> {
static final GlobalKey<PagedGridViewState> _gridKey = new GlobalKey<PagedGridViewState>();
String _path = mid.serverHttps ? "https://${mid.serverUrl}/"
: "http://${mid.serverUrl}/";
String _sortOrder;
final List<SortMethod> sortMethods = const <SortMethod>[
const SortMethod(value: 'alpha', title: "Alpha", icon: Icons.sort_by_alpha),
const SortMethod(value: 'older_first', title: "Older first", icon: Icons.autorenew),
const SortMethod(value: 'last_first', title: "Last first", icon: Icons.change_history),
];
Future<PageAnswer> request(int page, int pageSize) async {
PageAnswer answer = await mid.api.getItems(sortOrder: _sortOrder);
return answer;
}
void _handleTap(int lookId) {
print('tap:' + lookId.toString());
}
Widget adapt(Map map){
var photos = map["Photos"].split(";");
String photoName = photos[0].split("|")[0];
return new GestureDetector(
onTap: () {_handleTap(map["Id"]);},
child: new GridTile(
child: new Card(
child: new Stack(
fit: StackFit.expand,
children: <Widget>[
new Image.network(_path + photoName,
fit: BoxFit.fitHeight),
new Center(
child: new Text(
map["Title"],
textAlign: TextAlign.center,
)),
],
),
),
),
);
}
_onSortOrderChanged(String value) {
setState((){
_sortOrder = value;
_gridKey.currentState.Clear();
});
}
#override
void initState(){
super.initState();
_sortOrder = 'alpha';
}
#override
Widget build(BuildContext context) {
PagedGridView grid = new PagedGridView(
key: _gridKey,
pageRequest: request,
widgetAdapter: adapt,
numberColumns: 2,
);
DropdownButton ddl = new DropdownButton<String>(
value: _sortOrder,
items: sortMethods.map((SortMethod sort){
return new DropdownMenuItem(
value: sort.value,
child: new Row(children: <Widget>[new Icon(sort.icon), new Text(sort.title)],)
);
}).toList(),
onChanged: _onSortOrderChanged,
);
PopupMenuButton<ItemSorting> popSort = new PopupMenuButton<ItemSorting>(
icon: new Icon(Icons.sort),
itemBuilder: (BuildContext context) => <PopupMenuItem<ItemSorting>> [
const PopupMenuItem<ItemSorting>(
value: ItemSorting.alpha,
child: const Text('Sort Alpha')
),
const PopupMenuItem<ItemSorting>(
value: ItemSorting.last_first,
child: const Text('Sort Last First')
),
const PopupMenuItem<ItemSorting>(
value: ItemSorting.older_first,
child: const Text('Sort Older First')
)
],
onSelected: (ItemSorting action){
_onSortOrderChanged(action.toString().split('.')[1]);
},
);
return new Scaffold(
appBar: new AppBar(
title: new Text('My Items'),
actions: <Widget>[
popSort, //ddl,
],
),
body: new Center(
child: grid,
),
);
}
}
class SortMethod {
const SortMethod({this.title, this.icon, this.value});
final String title;
final IconData icon;
final String value;
}
Error stack:
E/flutter (15195): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (15195): type 'Future<Object>' is not a subtype of type 'FutureOr<PageAnswer>' where
E/flutter (15195): Future is from dart:async
E/flutter (15195): Object is from dart:core
E/flutter (15195): FutureOr is from dart:async
E/flutter (15195): PageAnswer is from file:///D:/Development/appli/lib/libraries/function_types.dart
E/flutter (15195):
E/flutter (15195): #0 MIDApi.getItems (file:///D:/Development/appli/lib/libraries/api.dart:35:8)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #1 _ItemsPageState.request (file:///D:/Development/appli/lib/pages/items.dart:30:39)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #2 PagedGridViewState.loadNext (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:191:38)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #3 PagedGridViewState.lockedLoadNext (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:178:22)
E/flutter (15195): #4 PagedGridViewState.initState (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:93:10)
E/flutter (15195): #5 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3734:58)
E/flutter (15195): #6 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #7 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #8 Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #9 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4637:14)
E/flutter (15195): #10 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #11 Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #12 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
E/flutter (15195): #13 Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
E/flutter (15195): #14 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
E/flutter (15195): #15 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #16 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #17 Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #18 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
E/flutter (15195): #19 Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
E/flutter (15195): #20 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
E/flutter (15195): #21 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #22 ParentDataElement.mount (package:flutter/src/widgets/framework.dart:3938:11)
E/flutter (15195): #23 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #24 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4742:32)
E/flutter (15195): #25 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #26 Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #27 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
E/flutter (15195): #28 Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
E/flutter (15195): #29 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
E/flutter (15195): #30 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3752:11)
E/flutter (15195): #31 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #32 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #33 Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #34 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3636:16)
E/flutter (15195): #35 Element.rebuild (package:flutter/src/widgets/framework.dart:3478:5)
E/flutter (15195): #36 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3605:5)
E/flutter (15195): #37 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3600:5)
E/flutter (15195): #38 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2890:14)
E/flutter (15195): #39 Element.updateChild (package:flutter/src/widgets/framework.dart:2693:12)
E/flutter (15195): #40 ComponentElement.performRebuild (packag
E/flutter (15195): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (15195): type 'Future<Object>' is not a subtype of type 'FutureOr<PageAnswer>' where
E/flutter (15195): Future is from dart:async
E/flutter (15195): Object is from dart:core
E/flutter (15195): FutureOr is from dart:async
E/flutter (15195): PageAnswer is from file:///D:/Development/appli/lib/libraries/function_types.dart
E/flutter (15195):
E/flutter (15195): #0 MIDApi.getItems (file:///D:/Development/appli/lib/libraries/api.dart:34:8)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #1 _ItemsPageState.request (file:///D:/Development/appli/lib/pages/items.dart:30:39)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #2 PagedGridViewState.onRefresh (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:160:38)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #3 PagedGridViewState.Clear (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:85:11)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #4 _ItemsPageState._onSortOrderChanged.<anonymous closure> (file:///D:/Development/appli/lib/pages/items.dart:67:29)
E/flutter (15195): #5 State.setState (package:flutter/src/widgets/framework.dart:1108:30)
E/flutter (15195): #6 _ItemsPageState._onSortOrderChanged (file:///D:/Development/appli/lib/pages/items.dart:65:5)
E/flutter (15195): #7 _ItemsPageState.build.<anonymous closure> (file:///D:/Development/appli/lib/pages/items.dart:114:9)
E/flutter (15195): #8 _PopupMenuButtonState.showButtonMenu.<anonymous closure> (package:flutter/src/material/popup_menu.dart)
E/flutter (15195): #9 _RootZone.runUnary (dart:async/zone.dart:1381:54)
E/flutter (15195): #10 _FutureListener.handleValue (dart:async/future_impl.dart:129:18)
E/flutter (15195): #11 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:633:45)
E/flutter (15195): #12 Future._propagateToListeners (dart:async/future_impl.dart:662:32)
E/flutter (15195): #13 Future._completeWithValue (dart:async/future_impl.dart:477:5)
E/flutter (15195): #14 Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:507:7)
E/flutter (15195): #15 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (15195): #16 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
I/flutter (15195): Another exception was thrown: type '() => Future<dynamic>' is not a subtype of type '() => Future<Null>'
E/flutter (15195): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (15195): type '() => Type' is not a subtype of type '(Object) => FutureOr<Object>'
E/flutter (15195): #0 _FutureListener.handleError (dart:async/future_impl.dart:145:11)
E/flutter (15195): #1 Future._propagateToListeners.handleError (dart:async/future_impl.dart:645:47)
E/flutter (15195): #2 Future._propagateToListeners (dart:async/future_impl.dart:666:24)
E/flutter (15195): #3 Future._completeError (dart:async/future_impl.dart:485:5)
E/flutter (15195): #4 _SyncCompleter._completeError (dart:async/future_impl.dart:55:12)
E/flutter (15195): #5 _Completer.completeError (dart:async/future_impl.dart:27:5)
E/flutter (15195): #6 MIDApi.getItems.<anonymous closure> (file:///D:/Development/appli/lib/libraries/api.dart)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #7 _RootZone.runUnary (dart:async/zone.dart:1381:54)
E/flutter (15195): #8 _FutureListener.handleValue (dart:async/future_impl.dart:129:18)
E/flutter (15195): #9 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:633:45)
E/flutter (15195): #10 Future._propagateToListeners (dart:async/future_impl.dart:662:32)
E/flutter (15195): #11 Future._complete (dart:async/future_impl.dart:467:7)
E/flutter (15195): #12 _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
E/flutter (15195): #13 ajaxGet (file:///D:/Development/appli/lib/libraries/ajax.dart)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #14 MIDApi.getItems (file:///D:/Development/appli/lib/libraries/api.dart:21:12)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #15 _ItemsPageState.request (file:///D:/Development/appli/lib/pages/items.dart:30:39)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #16 PagedGridViewState.onRefresh (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:160:38)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #17 PagedGridViewState.Clear (file:///D:/Development/appli/lib/widgets/paged_grid_view.dart:85:11)
E/flutter (15195): <asynchronous suspension>
E/flutter (15195): #18 _ItemsPageState._onSortOrderChanged.<anonymous closure> (file:///D:/Development/appli/lib/pages/items.dart:67:29)
E/flutter (15195): #19 State.setState (package:flutter/src/widgets/framework.dart:1108:30)
E/flutter (15195): #20 _ItemsPageState._onSortOrderChanged (file:///D:/Development/appli/lib/pages/items.dart:65:5)
E/flutter (15195): #21 _ItemsPageState.build.<anonymous closure> (file:///D:/Development/appli/lib/pages/items.dart:114:9)
E/flutter (15195): #22 _PopupMenuButtonState.showButtonMenu.<anonymous closure> (package:flutter/src/material/popup_menu.dart)
E/flutter (15195): #23 _RootZone.runUnary (dart:async/zone.dart:1381:54)
E/flutter (15195): #24 _FutureListener.handleValue (dart:async/future_impl.dart:129:18)
E/flutter (15195): #25 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:633:45)
E/flutter (15195): #26 Future._propagateToListeners (dart:async/future_impl.dart:662:32)
E/flutter (15195): #27 Future._completeWithValue (dart:async/future_impl.dart:477:5)
E/flutter (15195): #28 Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:507:7)
E/flutter (15195): #29 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (15195): #30 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)