Flutter BuildContext extension not working - flutter

Here is my extension file:
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
extension BuildContextExtensions on BuildContext {
void snack(String text){
ScaffoldMessenger.of(this).showSnackBar(SnackBar(content: Text(text)));
}
}
When I try to call it context.snack("asd"); it shows that The method 'snack' isn't defined for the type 'BuildContext'. And if I hover on the context it says package:flutter/src/widgets/framework.dart BuildContext get context

Solution was to manually import the file with the extension class into the file where it is used. Android studio didnt suggest me to import it. If i wrote the class name, only then it suggested to import it.

Every extension in dart needs a name, try adding a name to your extension
extension CustomSnackBar on BuildContext {
void snack(String text){
ScaffoldMessenger.of(this).showSnackBar(SnackBar(content: Text(text)));
}
}

Related

Flutter: Mock extension method using Mocktail (from EasyLocalization)

The flutter package easy_localization has an extention method on the BuildContext which looks like this:
Locale get deviceLocale => EasyLocalization.of(this)!.deviceLocale;
I wish to mock this using Mocktail.
I tried:
import 'package:mocktail/mocktail.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:test/test.dart';
class MockBuildContext extends Mock implements BuildContext {}
void main() {
test("Sample test", () {
final context = MockBuildContext();
when(() => context.deviceLocale).thenReturn(const Locale('en', 'US'));
expect(Locale('en', 'US'), context.deviceLocale);
});
}
However this throws an error: type 'Locale' is not a subtype of type '_EasyLocalizationProvider?'. I am assuming this happens because we are (unsuccessfully) trying to mock an Extension method and that the original method is called instead.
How can I mock the extension method to get the desired result?

FlutterError (Unable to load asset: assets/audio/assets/Sound3.mp3)

I want to play an audio as the app background music(without button click/autoplay). The code seen like no problem, but cant display.Did I do anything wrong with the code?
import 'package:flutter/material.dart';
import 'package:flame/game.dart';
import 'package:flame/input.dart';
import 'package:flame_audio/flame_audio.dart';
import 'package:flutter/widgets.dart';
void main() {
runApp(GameWidget(game: Audio()));
}
class Audio extends FlameGame with TapDetector {
#override
Future<void> onLoad() async {
super.onLoad();
}
#override
void onTapUp(TapUpInfo) {
FlameAudio.bgm.play('assets/Sound3.mp3');
}
}
pubspec.yaml
assets:
- assets/Sound3.mp3
[The Error Show in C:\flutter_windows_2.10.4-stable\flutter\packages\flutter\lib\src\services\asset_bundle.dart][1]
[1]: https://i.stack.imgur.com/p383i.png
const AssetImage('icons/heart.png', package: 'my_icons');
Assets used by the package (or plugin) itself should also be fetched using the package argument.
line: https://docs.flutter.dev/development/ui/assets-and-images

unable to register an abstract class in using injectable and get_it packages

I'm using injectable and get_it in flutter dart (following the very popular Reso coder)
I have a simple abstract class:
import 'package:injectable/injectable.dart';
//#injectable
abstract class IRandomQuantityRepository {
Future<int> getRandomQuantity();
}
and I have two simple concrete implementations of it:
import 'package:injectable/injectable.dart';
#dev
#injectable
class DevRandomQuantityRepository implements IRandomQuantityRepository {
const DevRandomQuantityRepository();
#override
Future<int> getRandomQuantity() async => 90;
}
and
import 'dart:math';
import 'package:injectable/injectable.dart';
#prod
#injectable
class RandomQuantityRepository implements IRandomQuantityRepository {
const RandomQuantityRepository();
#override
Future<int> getRandomQuantity() async => Random().nextInt(100);
}
Lastly, I have an injection.dart:
import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';
import 'package:moontreeapp/injection.config.dart';
final GetIt getIt = GetIt.instance;
#InjectableInit(preferRelativeImports: false)
void configureInjection(String env) {
$initGetIt(getIt, environment: env);
}
abstract class Env {
static const prod = 'prod';
static const dev = 'dev';
}
besides all that I have a bloc that wants to use stuff:
#injectable
class RandomQuantityBloc
extends Bloc<RandomQuantityEvent, RandomQuantityState> {
final IRandomQuantityRepository _quantityFacade; // notice this final...
doesn't that look good? I think so. So then I run this command to make the generated code flutter pub run build_runner watch
But I get a message:
[RandomQuantityBloc] depends on unregistered type [IRandomQuantityRepository]... Did you forget to annotate the above class(s) or their implementation with #injectable?
or add the right environment keys?
Ok, so that's cool, lets add it to the interface:
import 'package:injectable/injectable.dart';
#injectable // <-- added
abstract class IRandomQuantityRepository {
Future<int> getRandomQuantity();
}
but then I get a new error:
> [IRandomQuantityRepository] is abstract and can not be registered directly!
> if it has a factory or a create method annotate it with #factoryMethod
> 14 │ abstract class IRandomQuantityRepository {
> │ ^^^^^^^^^^^^^^^^^^^^^^^^^
In the past I've handled dependency injection manually, so I'm new to these packages, what am I missing here?
Besides all that, the real issue is that I can't switch the injection based on the environment. I can use get_it to get a concrete dependency but not one based on environment like in this test:
/// has no effect:
configureInjection(Env.dev);
/// gets prod version:
final devRandomQuantity = getIt<RandomQuantityRepository>();
So something about this whole set up isn't configuring the Injections correctly... What am I missing?
One final thing that might be useful is to see the generated code:
// GENERATED CODE - DO NOT MODIFY BY HAND
// **************************************************************************
// InjectableConfigGenerator
// **************************************************************************
import 'package:get_it/get_it.dart' as _i1;
import 'package:injectable/injectable.dart' as _i2;
import 'package:moontreeapp/application/quantity/bloc/randomquantity_bloc.dart'
as _i5;
import 'package:moontreeapp/domain/quantity/i_randomquantity_repository.dart' as _i6;
import 'package:moontreeapp/infrastructure/quantity/dev_randomquantity_repository.dart'
as _i3;
import 'package:moontreeapp/infrastructure/quantity/mock_randomquantity_repository.dart'
as _i4;
import 'package:moontreeapp/infrastructure/quantity/randomquantity_repository.dart'
as _i7;
const String _dev = 'dev';
const String _prod = 'prod';
// ignore_for_file: unnecessary_lambdas
// ignore_for_file: lines_longer_than_80_chars
/// initializes the registration of provided dependencies inside of [GetIt]
_i1.GetIt $initGetIt(_i1.GetIt get,
{String? environment, _i2.EnvironmentFilter? environmentFilter}) {
final gh = _i2.GetItHelper(get, environment, environmentFilter);
gh.factory<_i3.DevRandomQuantityRepository>(
() => _i3.DevRandomQuantityRepository(),
registerFor: {_dev});
gh.factory<_i5.RandomQuantityBloc>(
() => _i5.RandomQuantityBloc(get<_i6.IRandomQuantityRepository>()));
gh.factory<_i7.RandomQuantityRepository>(() => _i7.RandomQuantityRepository(),
registerFor: {_prod});
return get;
}
Do I put #injectable on abstract classes or not?
ok, so I guess injectable can't see what the class implements so you have to make it explicit. also, I missed that #dev isn't built in, you have to make it.
So this is the proper way to use the decorations
#Environment('dev')
#Injectable(as: IRandomQuantityRepository)
class DevRandomQuantityRepository implements IRandomQuantityRepository {
const DevRandomQuantityRepository();
#override
Future<Either<QuantFailure, Quantity>> getRandomQuantity() async =>
right(Quantity(Amount(900.0001), Decimal(4)));
}
and that way this does work:
configureInjection(Env.dev);
final mockRandomQuantity = getIt<IRandomQuantityRepository>();
await mockRandomQuantity.getRandomQuantity();
// 90

About errors in state management using freezed and StateNotifier in Flutter

I wrote the following code using freezed with the intention of managing the loading state when the sign-in button is pressed on the sign-in page.
//sign_in_page_state.dart
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter/foundation.dart';
import 'package:provider/provider.dart';
import 'package:state_notifier/state_notifier.dart';
part 'sign_in_page_state.freezed.dart';
#freezed
abstract class SignInPageState with _$SignInPageState {
const factory SignInPageState.noError() = _NoError;
const factory SignInPageState.error(String errorText) = _Error;
const factory SignInPageState.loading(String loadingText) = _Loading;
}
class SignInPageModel extends StateNotifier<SignInPageState>{
SignInPageModel(SignInPageState state):super(state);
void startSignIn(){
state=SignInPageState.loading("now signing in,please wait a minute.");
}
void successSignIn(){
state=SignInPageState.noError();
}
void errorSignIn(){
state=SignInPageState.error("failed to sign in.");
}
}
//signin_page.dart
class SignInPage extends StatefulWidget {
final String title = 'sign in';
static Widget create(BuildContext context,){
return StateNotifierProvider<SignInPageModel, SignInPageState>(
create:(_)=>SignInPageModel(SignInPageState.noError(),),
child:SignInPage(),
);
}
At this time, the following error will appear.
//error message
'SignInPageModel' doesn't conform to the bound 'StateNotifier<SignInPageState>' of the type parameter 'Controller'.
Try using a type that is or is a subclass of 'StateNotifier<SignInPageState>'.
No matter how I look at it, SignInPageModel is a subclass of StateNotifier<SignInPageState>.
and I also define and use UploadMovieState in much the same way as SignInPageState, but I don't get this error at all.
so I can't figure out the cause at all.
What could be the cause?
Since the State of SignInPage was declared as follows, it was caused by the same name 'SignInPageState'.
I'm sorry I asked a really silly question lol
class SignInPageState extends State<SignInPage> {
//...

ChangeNotifier can't no longer be used in Riverpod?

I am a beginner in Flutter, and I am trying to use Riverpod. here is the sample code
import "package:flutter_riverpod/flutter_riverpod.dart";
class CounterNotifier extends ChangeNotifier {
int _value = 0;
int get value => _value;
void incrementValue() {
_value++;
notifyListeners();
}
}
but I have error, I can't find ChangeNotifier and notifyListeners() like this
in pubspec.yaml file, I am using flutter_riverpod: ^0.14.0+3
am I misising something?
ChangeNotifier is a Flutter class, not a Riverpod one; when working with it, you have to ensure you have imported it.
It gets bundled in with common imports such as package:flutter/material.dart, and as Reign mentioned in his comment, can be directly imported via package:flutter/src/foundation/change_notifier.dart.