Here is code from one of the screens where I'm trying to use didChaneDependencies:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shop/screens/cart_screen.dart';
import '../widgets/products_grid.dart';
import '../widgets/badge.dart';
import '../widgets/app_drawer.dart';
import '../providers/products.dart';
import '../providers/cart.dart';
enum FilterOptions {
Favorites,
All,
}
class ProductsOverviewScreen extends StatefulWidget {
#override
_ProductsOverviewScreenState createState() => _ProductsOverviewScreenState();
}
class _ProductsOverviewScreenState extends State<ProductsOverviewScreen> {
var _showOnlyFavorite = false;
var _isInit = true;
#override
void initState() {
print('initState');
super.initState();
}
#override
void didChaneDependencies() {
print('didChaneDependencies');
super.didChangeDependencies();
}
Problem is that it does not fires up.
And the compiler highlights it with the following message:
The method doesn't override an inherited method. Try updating this
class to match the superclass, or removing the override annotation.
I did try remove the #override , but that did not fixed the problem, I cannot see
print('didChaneDependencies'); in the debugger.
Fix the spelling of the function name, You are missing a G in the didChangeDependencies function name
#override
void didChangeDependencies() {
....
Related
All of the sudden I am getting the error DataStore plugin has not been added to Amplify, recoverySuggestion: Add DataStore plugin to Amplify and call configure before calling DataStore related APIs to rule out any of the work I was doing on that page I tried it on a fresh page with the same result.
I already did execute amplify codegen models, amplify pull and amplify env pull. Also tried to do a flutter clean but I don't see any change at all. I'm really puzzled and can't seem to figure out the issue.
One thing I did notice while debugging was that the initState of the screen seems to be executed earlier as the configureAmplify callback.
I will show the relevant parts of the code (sorry for the long code in advance).
Pubspec.yaml
dependencies:
...
amplify_flutter: ^0.2.10
amplify_datastore: ^0.2.10
amplify_api: ^0.2.10
amplify_auth_cognito: ^0.2.10
amplify_storage_s3: ^0.2.10
main.dart
import 'package:flutter/material.dart';
import 'package:my_package/screens/main/teams_screen.dart';
import 'package:my_package/services/amplify_services.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
AmplifyService.configureAmplify();
}
#override
Widget build(BuildContext context) {
...
}
}
services/amplify_services.dart
import 'package:flutter/foundation.dart';
import 'package:amplify_flutter/amplify.dart';
import 'package:amplify_datastore/amplify_datastore.dart';
import 'package:amplify_api/amplify_api.dart';
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_storage_s3/amplify_storage_s3.dart';
import 'package:my_package/models/ModelProvider.dart';
import 'package:my_package/amplifyconfiguration.dart';
class AmplifyService {
static configureAmplify() async {
AmplifyAPI apiPlugin = AmplifyAPI();
AmplifyAuthCognito authPlugin = AmplifyAuthCognito();
AmplifyStorageS3 amplifyStorageS3 = AmplifyStorageS3();
AmplifyDataStore dataStorePlugin = AmplifyDataStore(
modelProvider: ModelProvider.instance,
);
await Amplify.addPlugins([
dataStorePlugin,
authPlugin,
amplifyStorageS3,
apiPlugin,
]);
try {
await Amplify.configure(amplifyconfig);
} on AmplifyAlreadyConfiguredException {
if (kDebugMode) {
print(
"Amplify was already configured. Looks like app restarted on android.");
}
}
}
}
Lastly the very basic page with not even an output (screens/teams_screen.dart)
import 'dart:async';
import 'package:amplify_datastore/amplify_datastore.dart';
import 'package:amplify_flutter/amplify.dart';
import 'package:flutter/material.dart';
import 'package:my_package/models/Team.dart';
class TeamsScreen extends StatefulWidget {
const TeamsScreen({Key? key}) : super(key: key);
#override
_TeamsScreenState createState() => _TeamsScreenState();
}
class _TeamsScreenState extends State<TeamsScreen> {
late StreamSubscription<QuerySnapshot<Team>> _teamsSubscription;
bool _isLoading = true;
List<Team> teams = [];
#override
void initState() {
super.initState();
_initializeApp();
}
#override
void dispose() {
_teamsSubscription.cancel();
super.dispose();
}
Future<void> _initializeApp() async {
_teamsSubscription = Amplify.DataStore.observeQuery(Team.classType)
.listen((QuerySnapshot<Team> snapshot) {
setState(() {
if (_isLoading) _isLoading = false;
teams = snapshot.items;
});
});
}
#override
Widget build(BuildContext context) {
return Container();
}
}
New day, fresh mind. The issue turned out to be quite simple, I didn't set an _isLoading state to indicate weter or not the configureAmplify callback was completed and let the app just continue loading all the other screens triggering the error. So after setting the state and only adding the rest of the app after the state was changed it worked without any problem.
To fix it I did the following:
import 'package:flutter/material.dart';
import 'package:my_package/screens/main/teams_screen.dart';
import 'package:my_package/services/amplify_services.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
_initializeApp();
}
Future<void> _initializeApp() async {
await AmplifyService.configureAmplify(); // note the await!
setState(() {
_isLoading = false; // important to set the state!
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: _isLoading
? Center(child: CircularProgressIndicator())
: const MainScreen(), // _isLoading is very important here.
);
}
}
I'm a beginner with tdd so please forgive me if it's a dumb question.
I'm having difficulty unit testing GetxControllers. Does anyone know a simple way of doing this?
Whenever I do I get errors since Get is calling onStart and it doesn't like the result Mockito's giving it. I've tried using Mockito 5.0.1's auto generated code as well as the older syntax, class MockController extends Mock implements Controller{}, as well as extends Fake.
The auto generated code has build errors, since Mockito is trying to use _InternalFinalCallback, but it's not being imported as it's private. I tried just copy pasting that part of the code into my generated file (and switching off pub build watch) but first that's a short term solution with it's own issues, 2nd it still doesn't work since the onStart and onDelete functions now tell me they're not valid overrides.
Also, I can see the get_test package but it's documentation is basically 0, and in the examples the controller is just used directly -- there's never a mocked controller.
I tried setting Get.testMode = true; but again that doesn't seem to do anything. And while I found that property in the docs, I didn't find how to use it correctly.
Any help would be appreciated,
Here's my code but the issue seems to be with the GetxControllers, so I don't think it's relevant much:
class FakeAuthController extends Fake implements AuthController {}
#GenerateMocks([AuthController])
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
late MockAuthController mockAuthController;
late FakeAuthController fakeAuthController;
late SessionController sessionController;
setUp(() {
Get.testMode = true;
mockAuthController = MockAuthController();
fakeAuthController = FakeAuthController();
Get.put<AuthController>(mockAuthController);
sessionController = SessionController();
});
tearDown(() {
Get.delete<AuthController>();
});
group('getSessionInfo', () {
test('Calls authFacade getSignedInUserId', () async {
await sessionController.getSessionInfo();
when(Get.find<AuthController>()).thenReturn(fakeAuthController);
verify(mockAuthController.getSignedInUserId());
});
});
}
There really isn't anything in my AuthController and session controller, but code is as follows:
import 'package:get/get.dart';
class AuthController extends GetxController {
String getSignedInUserId() {
// await Future.delayed(Duration(milliseconds: 1));
return '1';
}
}
import 'package:get/get.dart';
import '../../auth/controllers/auth_controller.dart';
import '../models/session_info.dart';
class SessionController extends GetxController {
final AuthController authController = Get.find<AuthController>();
Rx<SessionInfo> sessionInfo = Rx<SessionInfo>();
Future<void> getSessionInfo() async {
// authController.getSignedInUserId();
// sessionInfo.value = SessionInfo(userId: userId);
}
}
And the auto-generated, buggy mock controller:
// Mocks generated by Mockito 5.0.1 from annotations
// in smart_locker_controller/test/shared/controllers/session_controller_test.dart.
// Do not manually edit this file.
import 'dart:ui' as _i4;
import 'package:get/get_instance/src/lifecycle.dart' as _i2;
import 'package:get/get_state_manager/src/simple/list_notifier.dart' as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:smart_locker_controller/auth/controllers/auth_controller.dart'
as _i3;
// ignore_for_file: comment_references
// ignore_for_file: unnecessary_parenthesis
class _Fake_InternalFinalCallback<T> extends _i1.Fake
implements _i2._InternalFinalCallback<T> {}
/// A class which mocks [AuthController].
///
/// See the documentation for Mockito's code generation for more information.
class MockAuthController extends _i1.Mock implements _i3.AuthController {
MockAuthController() {
_i1.throwOnMissingStub(this);
}
#override
int get notifierVersion =>
(super.noSuchMethod(Invocation.getter(#notifierVersion), returnValue: 0)
as int);
#override
int get notifierMicrotask =>
(super.noSuchMethod(Invocation.getter(#notifierMicrotask), returnValue: 0)
as int);
#override
bool get hasListeners =>
(super.noSuchMethod(Invocation.getter(#hasListeners), returnValue: false)
as bool);
#override
int get listeners =>
(super.noSuchMethod(Invocation.getter(#listeners), returnValue: 0)
as int);
#override
_i2._InternalFinalCallback<void> get onStart =>
(super.noSuchMethod(Invocation.getter(#onStart),
returnValue: _Fake_InternalFinalCallback<void>())
as _i2._InternalFinalCallback<void>);
#override
_i2._InternalFinalCallback<void> get onDelete =>
(super.noSuchMethod(Invocation.getter(#onDelete),
returnValue: _Fake_InternalFinalCallback<void>())
as _i2._InternalFinalCallback<void>);
#override
bool get initialized =>
(super.noSuchMethod(Invocation.getter(#initialized), returnValue: false)
as bool);
#override
bool get isClosed =>
(super.noSuchMethod(Invocation.getter(#isClosed), returnValue: false)
as bool);
#override
String getSignedInUserId() =>
(super.noSuchMethod(Invocation.method(#getSignedInUserId, []),
returnValue: '') as String);
#override
void update([List<Object>? ids, bool? condition = true]) =>
super.noSuchMethod(Invocation.method(#update, [ids, condition]),
returnValueForMissingStub: null);
#override
void refreshGroup(Object? id) =>
super.noSuchMethod(Invocation.method(#refreshGroup, [id]),
returnValueForMissingStub: null);
#override
void removeListener(_i4.VoidCallback? listener) =>
super.noSuchMethod(Invocation.method(#removeListener, [listener]),
returnValueForMissingStub: null);
#override
void removeListenerId(Object? id, _i4.VoidCallback? listener) =>
super.noSuchMethod(Invocation.method(#removeListenerId, [id, listener]),
returnValueForMissingStub: null);
#override
_i5.Disposer addListener(_i5.GetStateUpdate? listener) =>
(super.noSuchMethod(Invocation.method(#addListener, [listener]),
returnValue: () {}) as _i5.Disposer);
#override
_i5.Disposer addListenerId(Object? key, _i5.GetStateUpdate? listener) =>
(super.noSuchMethod(Invocation.method(#addListenerId, [key, listener]),
returnValue: () {}) as _i5.Disposer);
#override
void disposeId(Object? id) =>
super.noSuchMethod(Invocation.method(#disposeId, [id]),
returnValueForMissingStub: null);
}
This question has now been answered in the GetX docs.
Pasted from the docs:
Tests
You can test your controllers like any other class, including their lifecycles:
class Controller extends GetxController {
#override
void onInit() {
super.onInit();
//Change value to name2
name.value = 'name2';
}
#override
void onClose() {
name.value = '';
super.onClose();
}
final name = 'name1'.obs;
void changeName() => name.value = 'name3';
}
void main() {
test('''
Test the state of the reactive variable "name" across all of its lifecycles''',
() {
/// You can test the controller without the lifecycle,
/// but it's not recommended unless you're not using
/// GetX dependency injection
final controller = Controller();
expect(controller.name.value, 'name1');
/// If you are using it, you can test everything,
/// including the state of the application after each lifecycle.
Get.put(controller); // onInit was called
expect(controller.name.value, 'name2');
/// Test your functions
controller.changeName();
expect(controller.name.value, 'name3');
/// onClose was called
Get.delete<Controller>();
expect(controller.name.value, '');
});
}
Mockito or mocktail
If you need to mock your GetxController/GetxService, you should extend GetxController, and mixin it with Mock, that way
class NotificationServiceMock extends GetxService with Mock implements NotificationService {}
Not exactly intuitive, is it?
Try changing your fake controller definition to:
class FakeAuthController extends GetxController with Fake implements AuthController {}
Not sure this works for Fake, but I just fixed a similar issue with Mock with it.
Problem
I'm using riverpod and state_notifier.
The initState() and update() that StateNotifier has are called and No. The other member functions can be called successfully. However, other member functions can be called successfully.
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:riverpod_todo_list/todo_list_notifier.dart';
import 'package:riverpod_todo_list/todo_list_state.dart';
void main() {
print('start~~');
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends HookWidget {
// ...
}
final todoListProvider = StateNotifierProvider((_) => TodoListNotifier());
class MyHomePage extends HookWidget {
final _controller = TextEditingController();
final todoListNotifier = useProvider(todoListProvider);
final TodoListState _todoListState =
useProvider(todoListProvider.state.select((value) => value));
//...
import 'package:riverpod_todo_list/todo.dart';
import 'package:riverpod_todo_list/todo_list_state.dart';
import 'package:state_notifier/state_notifier.dart';
import 'package:uuid/uuid.dart';
class TodoListNotifier extends StateNotifier<TodoListState> with LocatorMixin {
TodoListNotifier() : super(const TodoListState());
Uuid _uuid = Uuid();
// could not run.
#override
void initState() {
super.initState();
print('init state~~~');
}
// could not run.
#override
void update(Locator watch) {
super.update(watch);
print('update');
}
// could run.
void add(String title) {
Todo todo = Todo(id: _uuid.v4(), title: title);
List<Todo> todoList = []..addAll(state.todoList);
todoList.add(todo);
state = state.copyWith(todoList: todoList);
}
// could run.
void toggleStatus(int index) {
List<Todo> todoList = []..addAll(state.todoList);
todoList[index] = state.todoList[index]
.copyWith(completed: !state.todoList[index].completed);
state = state.copyWith(todoList: todoList);
print('changed toggle~~');
}
}
restarted logs
not put initState() and update() logs.
Performing hot restart...
Restarted application in 464ms.
flutter: start~~
The question is already answered on the Github.
LocatorMixin is not supported by Riverpod.
https://github.com/rrousselGit/river_pod/issues/75#issuecomment-671255330
And it's proposed to note it in the document.
In my opinion, LocatorMixin is not needed to use with Riverpod because of ProvidierReference.
final userRepositoryProvider = Provider((ref) => UserRepository());
final userControllerProvider = StateNotifierProvider((ref) {
return UserController(
// Read userRepositoryProvider and create a UserController from the result
repository: ref.watch(userRepositoryProvider),
);
});
I am creating a state machine with Dart,
I am stuck now, I usually did everything in C++, and I would just pass a pointer for a task like this, but in Dart, I am not sure how to do this.
Basically I have created:
class state
{
some methods
}
class MenuState extends State
{
overridden methods
}
now I need that my state machine class would take all children of the state as a correct argument,
So basically what I have written.
class StateMachine
{
StateMachine(State newState)
}
void main()
{
MenuState myMenuState = new MenuSatate();
StateMachine stateM = new StateMachine(myMenuState);
}
I get the error that I cannot pass the myMenuState even it is a child of State. How do I work this around in dart?
The code looks like this
main.dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flame/util.dart';
import 'package:flutter/services.dart';
import 'package:flutter/gestures.dart';
import 'package:flame/flame.dart';
import 'stateMachine/gameLoop.dart';
void main() async
{
WidgetsFlutterBinding.ensureInitialized();
Util flameUtil = Util();
await flameUtil.fullScreen();
await flameUtil.setOrientation(DeviceOrientation.portraitUp);
MyGame game = new MyGame();
runApp(game.widget);
}
state.dart
import 'dart:ui';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class MyState extends StatefulWidget
{
#override
MyState()
{
initialiaze();
}
void initialiaze() async
{
}
void render(Canvas canvas)
{
}
void update(double t)
{
}
void resize(Size size)
{
}
void onTapDown(TapDownDetails d)
{
}
#override
State<StatefulWidget> createState() {
// TODO: implement createState
throw UnimplementedError();
}
}
menuState.dart
import 'package:flutter/material.dart';
import '../stateMAchine/state.dart';
import 'package:flutter/gestures.dart';
import 'dart:ui';
class MenuState extends State<MyState>
{
#override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
#override
void initialiaze() async
{
print("menu State initliazed");
}
#override
void render(Canvas canvas)
{
}
#override
void update(double t)
{
}
#override
void resize(Size size)
{
}
#override
void onTapDown(TapDownDetails d)
{
}
}
stateMachine.dart
import "state.dart";
MyState stateReference;
class StateMachine
{
StateMachine(MyState ref)
{
initialiaze(ref);
}
void initialiaze(MyState ref) async
{
ref.initialiaze();
}
}
gameLoop.dart
this is there error comes, then I start to put menuState as an argument
import 'dart:ui';
import 'package:flame/flame.dart';
import 'package:flame/game.dart';
import 'dart:math';
import 'package:flutter/gestures.dart';
import 'stateMachine.dart';
import '../states/menuState.dart';
import 'state.dart';
class MyGame extends Game {
Size screenSize;
double tileSize;
MenuState menuState;
StateMachine stateMachine;
Random rnd;
MyGame()
{
initialiaze();
}
void initialiaze() async
{
resize(await Flame.util.initialDimensions());
rnd = Random();
menuState = new MenuState();
stateMachine = new StateMachine(menuState);
}
void render(Canvas canvas)
{
Rect bgRect = Rect.fromLTWH(0, 0, screenSize.width, screenSize.height);
Paint bgPaint = Paint();
bgPaint.color = Color(0xff576574);
canvas.drawRect(bgRect, bgPaint);
}
void update(double t)
{
}
void resize(Size size)
{
}
void onTapDown(TapDownDetails d)
{
}
}
I'm new in flutter development. I add onTapdown listener if i perform any clicked action on the screen. It's worked,but the problem is sometime when i clicked,onTapdown function not get called.I don't know what problem i have done.Hope can help me solve this problem.Thank you in advance.
import 'package:flame/game.dart';
import 'package:flame/components/parallax_component.dart';
import 'package:flame/util.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
Util flameUtil = Util();
await flameUtil.fullScreen();
runApp(MyGame(flameUtil).widget);
}
class MyGame extends BaseGame {
MyGame(Util flameUtil) {
final images = [
ParallaxImage("space/bg_base.png",repeat: ImageRepeat.repeat,fill: LayerFill.height),
ParallaxImage("space/bg_big_star.png",repeat: ImageRepeat.repeatY,fill: LayerFill.height),
ParallaxImage("space/bg_planet.png",repeat: ImageRepeat.repeat,fill: LayerFill.none),
];
var game = Squres(images);
add(game);
TapGestureRecognizer tapper = TapGestureRecognizer();
tapper.onTapDown = game.onTapDown;
flameUtil.addGestureRecognizer(tapper);
}
}
class Squres extends ParallaxComponent{
Squres(List<ParallaxImage> images) : super(images){
baseSpeed = const Offset(4,0);
layerDelta = const Offset(0,-50);
}
#override
void render(Canvas canvas) {
super.render(canvas);
}
#override
void resize(Size size) {
super.resize(size);
}
#override
void update(double t) {
super.update(t);
}
//not always trigger
void onTapDown(TapDownDetails tap){
print("trigger");
}
}
Make sure you use flame 0.22.0^ and use create your game class like this instead:
class MyGame extends BaseGame with TapDetector {
Squres game;
MyGame() {
final images = [
ParallaxImage("space/bg_base.png",repeat: ImageRepeat.repeat,fill: LayerFill.height),
ParallaxImage("space/bg_big_star.png",repeat: ImageRepeat.repeatY,fill: LayerFill.height),
ParallaxImage("space/bg_planet.png",repeat: ImageRepeat.repeat,fill: LayerFill.none),
];
game = Squres(images);
add(game);
}
#override
void onTapDown(TapUpDetails details) {
print("trigger");
game.onTapDown(details);
}
}
Also, remember that you don't have to override update, resize and render if you only call super on them.