LocationListBloc doesnt extend Bloc<dynamic, LocationListState> - flutter

I am currently refactoring my code to the bloc pattern and have created a bloc for a screen that fetches a list of locations from a json file in assets. The event being the fetch, and the states being initial, loading and loaded.
On my UI screen, I want to use BlocBuilder but when I use the BlocBuilder widget it gives me the error :
LocationListBloc doesnt extend Bloc with the LocationListBloc underlined with a line
My code is structured in folders as as follows
lib/blocs/location_list_bloc
lib/blocs/location_list_event
lib/blocs/location_list_state
lib/blocs/blocs
UI / location_list
location_list_state
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:gt_project_bloc/blocs/blocs.dart';
class Locations extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BlocBuilder<LocationListBloc, LocationListState>();
}
}
import 'package:equatable/equatable.dart';
import 'package:gt_project_bloc/models/models.dart';
import 'package:meta/meta.dart';
import 'package:equatable/equatable.dart';
abstract class LocationListState extends Equatable {
const LocationListState();
#override
List<Object> get props => [];
}
class LocationListinitial extends LocationListState {}
class LocationListLoading extends LocationListState {}
class LocationListLoaded extends LocationListState {
final List<SavedStations> locationlist;
LocationListLoaded(this.locationlist) : assert(locationlist != null);
}
location_list_event
import 'package:equatable/equatable.dart';
abstract class LocationListEvent extends Equatable {
#override
List<Object> get props => [];
}
class Fetch extends LocationListEvent {}
location_list_state
import 'package:equatable/equatable.dart';
import 'package:gt_project_bloc/models/models.dart';
import 'package:meta/meta.dart';
import 'package:equatable/equatable.dart';
abstract class LocationListState extends Equatable {
const LocationListState();
#override
List<Object> get props => [];
}
class LocationListinitial extends LocationListState {}
class LocationListLoading extends LocationListState {}
class LocationListLoaded extends LocationListState {
final List<SavedStations> locationlist;
LocationListLoaded(this.locationlist) : assert(locationlist != null);
}

I found my issue, i had a stateful widget on the same page called LocationList and it was confusing its state LocationListState with the same name of my blocs state

Related

Flutter Bloc: state not rebuilding

I have a bloc listening to chats. Through the debugger, I can see that the bloc is catching live updates. However, the ui is not rebuilding when these changes occur. To see a change, I have to leave and reload the screen.
My chat state:
part of 'chat_bloc.dart';
abstract class ChatState extends Equatable {
const ChatState();
#override
List<Object?> get props => [];
}
class ChatLoading extends ChatState {}
class ChatLoaded extends ChatState {
final List<Chat?>? compiledChats;
const ChatLoaded({required this.compiledChats});
#override
List<Object?> get props => [compiledChats];
}
My chat events:
part of 'chat_bloc.dart';
abstract class ChatEvent extends Equatable {
const ChatEvent();
#override
List<Object?> get props => [];
}
class LoadChat extends ChatEvent {
const LoadChat();
#override
List<Object> get props => [];
}
class CloseChat extends ChatEvent {
const CloseChat();
#override
List<Object?> get props => [];
}
class UpdateChat extends ChatEvent {
final List<List<Chat?>> chats;
const UpdateChat({required this.chats});
#override
List<Object> get props => [chats];
}
My actual bloc:
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:hero/blocs/auth/auth_bloc.dart';
import 'package:hero/models/chat_model.dart';
import 'package:hero/models/user_model.dart';
import 'package:hero/repository/firestore_repository.dart';
part 'chat_event.dart';
part 'chat_state.dart';
class ChatBloc extends Bloc<ChatEvent, ChatState> {
final FirestoreRepository _firestoreRepository;
late StreamSubscription _chatListener;
ChatBloc({
required FirestoreRepository firestoreRepository,
}) : _firestoreRepository = firestoreRepository,
super(ChatLoading()) {
on<LoadChat>(_onLoadChat);
on<UpdateChat>(_onUpdateChat);
on<CloseChat>(_onCloseChat);
}
void _onLoadChat(
LoadChat event,
Emitter<ChatState> emit,
) {
_chatListener = _firestoreRepository.chats.listen((chats) {
add(
UpdateChat(
chats: chats,
),
);
});
}
void _onUpdateChat(
UpdateChat event,
Emitter<ChatState> emit,
) {
//generate compiledChats from event.chats
List<Chat?>? compiledChats = [];
for (List<Chat?> chatList in event.chats) {
for (Chat? chat in chatList) {
if (chat != null) {
compiledChats.add(chat);
}
}
}
emit(ChatLoaded(compiledChats: compiledChats));
}
void _onCloseChat(
CloseChat event,
Emitter<ChatState> emit,
) {
_chatListener.cancel();
print('ChatBloc disposed');
emit(ChatLoading());
}
#override
Future<void> close() async {
super.close();
}
}
For the scope of this problem, all that really matters is just looking at the updateChat and LoadChat methods. Any ideas? Thanks!

Flutter - How to retrieve an implemented class with Get.find after registered with Get.put using GetX?

I have a class called GetConnectApiHelper that implemented an abstraction called IApiHelper, I need to register this class with Get.put inside Bindings and retrieve the implementation inside an abstraction variable but when I try to do that I get an error about "the abstraction is not registered".
How can I inject the dependency correctly making it easy to change in case I need to replace with http, dio etc...(clean architecture)
abstract class IApiHelper {}
class GetConnectApiHelper extends GetxService implements IApiHelper {}
class SignInBinding extends Bindings {
#override
void dependencies() {
Get.put(GetConnectApiHelper());
Get.put(SignInController());
}
}
class SignInController extends GetxController {
final IApiHelper apiHelper = Get.find(); // This throws the exception
}
======== Exception caught by widgets library =======================================================
The following message was thrown building Builder(dirty):
"IApiHelper" not found. You need to call "Get.put(IApiHelper())" or "Get.lazyPut(()=>IApiHelper())"
I found a solution. I can set the Interface as a Type and then register the implementation I want to be retrieved.
class SignInBinding extends Bindings {
#override
void dependencies() {
Get.put<IApiHelper>(GetConnectApiHelper());
Get.put(SignInController());
}
}
class SignInController extends GetxController {
final IApiHelper apiHelper = Get.find();
}
print(apiHelper.runtimeType); // it prints Instance of 'GetConnectApiHelper'
Or I can inject the implementation.
class SignInBinding extends Bindings {
#override
void dependencies() {
Get.put<IApiHelper>(GetConnectApiHelper());
Get.put(SignInController(apiHelper: Get.find()));
}
}
class SignInController extends GetxController {
final IApiHelper apiHelper;
SignInController({required this.apiHelper})
}
GetX finds its dependencies based on its exact types so you need to use Get.find<GetConnectApiHelper>()
updated:
class SignInBinding extends Bindings {
#override
void dependencies() {
Get.put(GetConnectApiHelper());
Get.put(SignInController<GetConnectApiHelper>());
}
}
class SignInController<T extends IApiHelper> extends GetxController {
final IApiHelper apiHelper = Get.find<T>();
}

Alias one imported class in Dart

I want to create a base class for my Flutter widgets:
import 'package:flutter/widgets.dart';
abstract class State extends State {
#override
Widget build(BuildContext context) {
// ...
}
// ...
}
Like this, it results in the error "State' can't extend itself." which makes perfect sense. To fix it I can do this:
import 'package:flutter/widgets.dart' as base;
abstract class State extends base.State {
But now I have to prefix all other framework classes with "base.". Is there a way to alias just the State class and use everything else without a prefix?
This seems to have worked:
import 'package:flutter/material.dart';
import 'package:flutter/material.dart' as base show State;
abstract class State<T extends StatefulWidget> extends base.State {
#override
Widget build(BuildContext context) {
// ...
}
}

didChaneDependencies not working / flutter

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() {
....

How to use Freezed package with Bloc in flutter?

I want to create a simple bloc with freezed package. This is my bloc:
import 'package:bloc/bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:presentation/presentation_index.dart';
part 'auth_bloc_event.dart';
part 'auth_bloc_state.dart';
class AuthBlocBloc extends Bloc<AuthEvent, AuthState> {
final SignUpBuyerUseCase signUpBuyerUseCase;
AuthBlocBloc(this.signUpBuyerUseCase) : super(AuthState.initial());
#override
Stream<AuthState> mapEventToState(
AuthEvent event,
) async* {
yield* event.map();
}
}
and my event class :
part of 'auth_bloc.dart';
#freezed
abstract class AuthEvent with _$AuthEvent {
const factory AuthEvent.login(String username, String password) = Login;
const factory AuthEvent.signUpBuyer(BuyerEntity entity) = SignUpBuyer;
}
and state class :
part of 'auth_bloc.dart';
#freezed
abstract class AuthState with _$AuthState {
const factory AuthState.initial() = InitialAuthState;
const factory AuthState.signUpBuyerFail(String error) = SignUpBuyerFail;
const factory AuthState.signUpBuyerSuccess() = SignUpBuyerSuccess;
const factory AuthState.signUpBuyerLoading() = SignUpBuyerLoading;
}
The problem is that when i try to run
flutter pub run build_runner watch --deleteonflicting-outputs
Nothing happens and no classes are generated
In the bloc, you should try to include the freezed file.
part 'auth_bloc_event.dart';
part 'auth_bloc_state.dart';
part 'auth_bloc.freezed.dart';