Se você utiliza o Bloc
como gerenciador de estado já se deparou com a situação na qual você precisa invocá-lo para realizar uma chamada específica. Uma das formas para isso é utilizarmos as extensões de contexto.
Por que isso importa
Entender como utilizar as extensões de contexto nos permitirá obter a instância mais próxima do Bloc
naquele contexto sem termos a necessidade de instanciá-lo.
No entanto, é importante ter cuidado com algumas armadilhas.
Cuidado para não utilizá-lo para observar estados
O context.read
só captura o estado atual no momento no qual ele é chamado e não recebe as novas atualizações. Isso significa que, se estivermos utilizando-o para obter novas informações do estado teremos um problema de consistência de dados em tela.
Cuidado para não pedí-lo fora do contexto correto
Outro problema comum é tentar acessar o Bloc
por meio da extensão de contexto fora do contexto no qual ele foi provisionado. Isso resultará em uma exceção, pois o Bloc não estará disponível naquele contexto específico.
Como funciona
Quando utilizamos o context.read
o que estamos fazendo é percorrer a árvore de widgets em busca de um BlocProvider
que tenha sido responsável por provisionar o Bloc
que estamos buscando.
Exemplo prático
Definição do cubit
import 'package:flutter_bloc/flutter_bloc.dart';
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
void decrement() => emit(state - 1);
}
class UserProfileState {
UserProfileState({required this.name});
final String name;
}
class UserProfileCubit extends Cubit<UserProfileState> {
UserProfileCubit() : super(UserProfileState(name: 'John Doe'));
void changeName(String newName) => emit(UserProfileState(name: newName));
}
Construção da UI
class MyApp extends StatelessWidget {
@override Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider(create: (_) => CounterCubit()),
BlocProvider(create: (_) => UserProfileCubit()),
],
child: MaterialApp( home: HomeScreen(), ),
);
}
}
class HomeScreen extends StatelessWidget {
@override Widget build(BuildContext context) {
final count = context.watch<CounterCubit>().state;
final userName = context.select<UserProfileCubit, String>((cubit) => cubit.state.name);
return Scaffold(
appBar: AppBar(title: Text('Exemplo de Context Watch e Select')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Valor do Contador: $count',
style: TextStyle(fontSize: 20)
),
SizedBox(height: 20),
Text(
'Nome do Usuário: $userName',
style: TextStyle(fontSize: 20)
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () => context.read<CounterCubit>().increment(),
child: Text('Incrementar Contador'),
),
ElevatedButton(
onPressed: () => context.read<UserProfileCubit>().changeName('Jane Doe'),
child: Text('Mudar Nome do Usuário'),
),
],
),
),
);
}
}
Conclusão
No exemplo anterior, demonstramos na prática o uso das extensões de contexto. Saber aplicar o context.read
tornará sua vida um pouco mais fácil para acessar funções do Bloc
desejado.
Nos próximos artigos iremos abordar o uso das outras extensões de contexto como context.select
e context.watch
, as quais trarão mais reatividade na construção dos nossos Widgets
.
Até lá!