class constructor after inheritance - flutter

i'm new to flutter i can't get the constructor to work which is in comment,
but the other constructor works, why? thank you
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: ImageEditor()
// child: PhotoView(imageProvider: AssetImage("Assets/img/carte.png"),)
);
}
}
class ImageEditor extends PhotoView {
// ignore: missing_required_param
ImageEditor():super(imageProvider: AssetImage("Assets/img/carte.png"),){
init();
}
//ImageEditor(){
// super(imageProvider: AssetImage("Assets/img/carte.png"),);
// init()
// }
void init(){
if(imageProvider!=null) {
print("il y a peut etre moyen de dessiner sur l'image");}
}
}

This is what you call a super constructor.
ImageEditor():super(imageProvider: AssetImage("Assets/img/carte.png")){
init();
}
Normally, a subclass can inherit all the variables and function from the parent class(using the extends) keyword, but you cannot access its constructor.
Using the : super() argument, you can however call the constructor from the parent class. You can only do it that way, that is simply the syntax.
Example:
class Class1 {
Class1(String name) {
print("Hello $name");
}
}
class Class2 extends Class1 {
Class2() : super("Tom") { //the name from above
print("Hello World");
}
}
void main() {
Class2 test = new Class2();
}
The output would be(in that order):
Hello Tom
Hello World

Related

Call super method of super class from child class

I have an abstract class A:
abstract class A {
Future<String> firstMethod();
}
and I implemented this abstract class:
class Aimp implements A {
#override
Future<String> firstMethod() async {
return "test";
}
}
I have created another abstract class:
abstract class B extends A {
Future<String> secondMethod();
}
and I implemented this abstract class:
class Bweb extends B {
#override
Future<Object> secondMethod() async {
final t = //I want to call firstMethod()
if(t.isNotEmpty()) // do sth
}
}
In the implementation of secondMethod(), how can I call the implementation of firstMethod()?
I don't want to use mixin.
I try to use with instead:
abstract class A {
Future<String> firstMethod();
}
class Aimp implements A {
#override
Future<String> firstMethod() async {
return "test";
}
}
abstract class B with Aimp {
Future<String> secondMethod();
}
class Bweb extends B {
#override
Future<String> secondMethod() async {
final String t = await firstMethod(); //Your firstMethod function
if(t.isNotEmpty) {
return t;
}
return '';
}
}
Then you need an object of Aimp class item as a field of Bweb class. Or place A class as a field for the B one.

Unit Test Concrete Method of Abstract Class in Dart

I have an abstract class written in Dart, that not only contains abstract method but also contains concrete methods like below:
abstract class Person {
void speak();
Foot getFoot();
void walk() {
getFoot().move();
}
}
class Foot {
void move() {
}
}
Test:
class MockPerson extends Person {
#override
Foot getFoot() {
return Foot();
}
#override
void speak() {
}
}
void main() {
late MockPerson sut;
setUp(() {
sut = MockPerson();
});
test('test walk', () {
/// ??
});
}
I tried to created mock of Person to be able to test against it. But I'm not sure how can I write unit test for walk() method?

Error: Type argument 'T' doesn't conform to the bound 'Object' of the type variable 'T' on 'GetIt.call'. After migrating to Null Safety

I'm in the process of migrating over a large project to null safety and I'm coming across a strange error I'm not entirely sure how to fix.
"Error: Type argument 'T' doesn't conform to the bound 'Object' of the type variable 'T' on 'GetIt.call'."
class BaseView<T extends BaseProvider?> extends StatefulWidget {
final Widget Function(BuildContext context, T value, Widget? child)? builder;
final Function(T)? onModelReady;
BaseView({this.builder, this.onModelReady});
#override
_BaseViewState<T> createState() => _BaseViewState<T>();
}
class _BaseViewState<T extends BaseProvider?> extends State<BaseView<T?>> {
T model = locator<T>(); <---- This is throwing it
#override
void initState() {
if (widget.onModelReady != null) {
widget.onModelReady!(model);
}
super.initState();
}
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<T?>(
create: (context) => model,
child: Consumer<T>(builder: widget.builder!),
);
}
}
I can't find much info on this error and so far any method I've tried hasn't worked out. Can anyone be of assistance?
I'm using Provider for state management and BaseView is what wraps all my other views during build; e.g.:
class EquipmentMainView extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BaseView<EquipmentProvider>(
onModelReady: (model) async {
model.getAllFunctions();
},..
Posting here for anyone else that might eventually run across this in the future, just changed the nullability of BaseProvider suggested by jamesdlin by changing
class BaseView<T extends BaseProvider?>
to
class BaseView<T extends BaseProvider>
I had similar issues when I upgraded to flutter 2.0 I made the generic methods in Generic class to explicitly extends Base class Object i.e
from:
import 'package:get_it/get_it.dart';
class PoultryBabaRegistry<T> {
static GetIt _getIt = GetIt.instance;
static void register<T>(T model) {
_getIt.registerSingleton<T extends Object >(model, signalsReady: true);
}
static void remove<T>(T model) {
_getIt.unregister<T extends Object>(instance:model);
}
static T getIt<T>() {
return _getIt.get<T>();
}
}
to:
class PoultryBabaRegistry<T extends Object> {
static GetIt _getIt = GetIt.instance;
static void register<T extends Object>(T model) {
_getIt.registerSingleton<T >(model, signalsReady: true);
}
static void remove<T extends Object>(T model) {
_getIt.unregister<T>(instance:model);
}
static T getIt<T extends Object>() {
return _getIt.get<T>();
}
}

State doesn't change in Flutter app using BLoC

I'm building an app which fetches hotel names from an API. I'm using the BLoC library. I managed to create whole service which downloads the data, but the result doesn't show in my terminal.
My BLoC works, it downloads the data. I saw it in Dart DevTools, but the state doesn't change and it does not show up.
Here's my code:
hotel_bloc.dart
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:hotels/controllers/hotel/hotel_controller.dart';
import 'package:hotels/models/hotel/hotel_model.dart';
import 'package:meta/meta.dart';
part 'hotel_event.dart';
part 'hotel_state.dart';
class HotelBloc extends Bloc<HotelEvent, HotelState> {
HotelBloc() : super(HotelLoading());
final HotelController hotelController = HotelController();
#override
Stream<HotelState> mapEventToState(
HotelEvent event,
) async* {
if (event is FetchEvent) {
yield HotelLoading();
try {
final Hotels hotels = await hotelController.parseHotels();
yield HotelFinal(hotels);
} catch (error) {
HotelError(error);
}
}
}
}
hotel_state.dart
part of 'hotel_bloc.dart';
#immutable
abstract class HotelState {
HotelState();
}
class HotelFinal extends HotelState {
final Hotels hotels;
HotelFinal(this.hotels);
Hotels getHotel() {
return hotels;
}
}
class HotelLoading extends HotelState {
HotelLoading();
}
class HotelError extends HotelState {
final String error;
HotelError(this.error);
}
hotel_event.dart
part of 'hotel_bloc.dart';
#immutable
abstract class HotelEvent {
HotelEvent();
}
class FetchEvent extends HotelEvent {
FetchEvent();
}
hotel_service.dart
import 'package:http/http.dart' as http;
abstract class DownloadService {
Future<http.Response> fetchHotels();
}
class HotelService extends DownloadService {
#override
Future<http.Response> fetchHotels() {
final Uri uri = Uri.https('services.lastminute.com', 'mobile/stubs/hotels');
return http.get(uri);
}
}
hotel_controller.dart
import 'package:hotels/models/hotel/hotel_model.dart';
import 'package:hotels/services/hotel/hotel_service.dart';
class HotelController {
final HotelService hotelService = HotelService();
Future<Hotels> parseHotels() async {
final response = await hotelService.fetchHotels();
final hotels = hotelsFromJson(response.body);
return hotels;
}
}
And finally the HomeScreen
home_screen.dart
import 'package:flutter/material.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hotels/blocs/hotel/hotel_bloc.dart';
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
HotelBloc hotelBloc;
#override
void initState() {
hotelBloc = HotelBloc()..add(FetchEvent());
super.initState();
}
#override
void dispose() {
hotelBloc.close();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('title').tr(),
),
body: BlocConsumer<HotelBloc, HotelState>(
listener: (context, state) {
if (state is HotelError) {
print(state.error);
}
},
builder: (context, state) {
if (state is HotelLoading) {
print('It\'s loading!');
}
if (state is HotelFinal) {
print(state.hotels.toString());
}
return Text('Default text');
},
),
);
}
}
The result is this:
The problem is the you haven't provided the BlocConsumer with your hotelBloc. You want to either have BlocProvider as a parent or use the cubit parameter on BlocConsumer.
BlocConsumer<HotelBloc, HotelState>(
cubit: hotelBloc,
listener:...
builder:...
)

How to use the BLoC library?

I'm trying to figure out the BLoC library, but it gives me headaches.
I'm trying to fetch hotel names from an API. I have a model and a service responsible for contacting the API and fetching the data. However, I don't know how to connect it to the BLoC library.
Once my app starts, I want BLoC to fetch the data from the API and then show it in the app.
Here's my code:
hotel_model.dart
class Hotels {
final List<Hotel> hotels;
Hotels({this.hotels});
factory Hotels.fromJson(Map<String, dynamic> json) {
return Hotels(
hotels: List<Hotel>.from(
json['hotels'].map(
(x) => Hotel.fromJson(x),
),
),
);
}
}
class Hotel {
final String hotelName;
Hotel({this.hotelName});
factory Hotel.fromJson(Map<String, dynamic> json) {
return Hotel(
hotelName: json['name'],
);
}
}
hotel_service.dart
import 'package:http/http.dart' as http;
abstract class DownloadService {
Future<http.Response> fetchHotels();
}
class HotelService extends DownloadService {
#override
Future<http.Response> fetchHotels() {
final Uri uri = Uri.https('services.lastminute.com', 'mobile/stubs/hotels');
return http.get(uri);
}
}
And here's what I did wit the BLoC lib.
hotel_event.dart
part of 'hotel_bloc.dart';
#immutable
abstract class HotelEvent {}
class OnAppStartEvent extends HotelEvent {}
hotel_bloc.dart
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:hotels/models/hotel/hotel_model.dart';
import 'package:hotels/services/hotel/hotel_service.dart';
import 'package:meta/meta.dart';
part 'hotel_event.dart';
part 'hotel_state.dart';
class HotelBloc extends Bloc<HotelEvent, HotelState> {
HotelBloc() : super(HotelFinal());
final HotelService hotelService = HotelService();
#override
Stream<HotelState> mapEventToState(
HotelEvent event,
) async* {
if (event is FetchEvent) {
final response = hotelService.fetchHotels();
yield
}
}
}
hotel_state.dart
part of 'hotel_bloc.dart';
#immutable
abstract class HotelState {
HotelState();
}
class HotelFinal extends HotelState {
final Hotel hotel;
HotelFinal(this.hotel);
Hotel getHotel() {
return hotel;
}
}
First of all add await to this line in your bloc
final response = await hotelService.fetchHotels();
return List<Hotel> from your fetchHotels function
you must have stateful class for your screen and in the initState
you can create your bloc object and call .add method on it
in your build method wrap your widget with BlocBuilder and on builder callback check your bloc state, if the state is HotelFinal return your ui with list of hotels in your state object.
It'll be useful to add another state for your HotelState for when your bloc is fetching the data, and even for when there's an error. e.g;
part of 'hotel_bloc.dart';
#immutable
abstract class HotelState {
HotelState();
}
class HotelFinal extends HotelState {
final Hotel hotel;
HotelFinal(this.hotel);
Hotel getHotel() {
return hotel;
}
}
class HotelLoading extends HotelState {
HotelLoading();
}
class HotelError extends HotelState {
final String error;
HotelError(this.error);
}
You would want to change your mapEventToState to something like this:
#override
Stream<HotelState> mapEventToState(
HotelEvent event,
) async* {
if (event is FetchEvent) {
yield HotelLoading();
try {
final response = await hotelService.fetchHotels();
// It seems like your service doesn't return an hotel directly, so you'll have to deal with this as it is not part of the question.
final hotel = getYourHotelHereWithTheResponse;
yield HotelFinal(hotel);
} catch (e) {
yield HotelError('something went wrong getting the hotel info');
}
}
}
Lastly, add a widget to your widget tree that adds FetchEvent to your bloc and add a BlocBuilder to react to the change of states. Note that this is very flexible and can be done in many ways, but it is out of the scope of your very broad question, I'm just showing you how to use the library at a minimal:
class MyStatefulWidget extends StatefulWidget {
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
HotelBloc hotelBloc;
#override
void initState() {
hotelBloc = HotelBloc..add(FetchEvent());
super.initState();
}
#override
void dispose() {
hotelBloc.close();
super.dispose();
}
#override
Widget build(BuildContext context) {
return BlocBuilder(builder: (context, state) {
if(state is HotelLoading) {
// return a widget to deal with loading
}
if(state is HotelFinal) {
// return a widget to deal with success
}
if(state is HotelError) {
// return a widget to deal with error
}
});
}
}