Skip to content

Instantly share code, notes, and snippets.

@libindev
Last active December 10, 2021 05:45
Show Gist options
  • Save libindev/d8dc751c07d5e97b585a319b87c35220 to your computer and use it in GitHub Desktop.
Save libindev/d8dc751c07d5e97b585a319b87c35220 to your computer and use it in GitHub Desktop.
Bloc flutter sample.
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_sample_api_bloc/bloc/user_bloc.dart';
import 'package:flutter_sample_api_bloc/bloc/user_detail_bloc.dart';
import 'package:flutter_sample_api_bloc/repository/sample_api_client.dart';
import 'package:flutter_sample_api_bloc/repository/sample_api_repository.dart';
import 'package:flutter_sample_api_bloc/widgets/userview.dart';
import 'package:http/http.dart' as http;
void main() {
final UserRepository employeeRepository = UserRepository(
employeeApiClient: EmployeeApiClient(
httpClient: http.Client(),
),
);
BlocSupervisor.delegate = SimpleBlocDelegate();
runApp(
App(employeeRepository: employeeRepository, title: "Employee App"));
}
class SimpleBlocDelegate extends BlocDelegate {
@override
void onEvent(Bloc bloc, Object event) {
super.onEvent(bloc, event);
print(event);
}
@override
onTransition(Bloc bloc, Transition transition) {
super.onTransition(bloc, transition);
print(transition);
}
@override
void onError(Bloc bloc, Object error, StackTrace stacktrace) {
super.onError(bloc, error, stacktrace);
print(error);
}
}
class App extends StatelessWidget {
final UserRepository employeeRepository;
final String title;
App({Key key, @required this.employeeRepository, @required this.title})
: assert(employeeRepository != null),
super(key: key);
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<UserBloc>(
create: (context) => UserBloc(employeeRepository: employeeRepository )),
BlocProvider<UserDetailBloc>(
create: (context) => UserDetailBloc(userRepository: employeeRepository))],
child: MaterialApp(
title: 'Employee App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: new Text( this.title ),
elevation: 4.0,
),
body: UserView())));
}
}
//BlocProvider(create: (context) =>EmployeeDetailBloc(employeeRepository: employeeRepository),
// child:
import 'dart:async';
import 'dart:convert';
import 'package:flutter_sample_api_bloc/model/user_data.dart';
import 'package:flutter_sample_api_bloc/model/user_detail.dart';
import 'package:http/http.dart' as http;
import 'package:meta/meta.dart';
class EmployeeApiClient {
static const baseUrl = 'https://reqres.in/api/users';
final http.Client httpClient;
EmployeeApiClient({@required this.httpClient}) : assert(httpClient != null);
Future<List<User>> getAllUser() async {
final userUrl = '$baseUrl?page=2';
final res = await this.httpClient.get( userUrl );
if (res.statusCode != 200) {
throw Exception( 'error getting employee data');
}
final jsonResponse = json.decode( res.body );
UserResponse userResponse = UserResponse.fromJson( jsonResponse );
return userResponse.user;
}
Future<UserDetail> getUserDetail(int user_id) async {
final slash ="/";
final usersDetailUrl = '$baseUrl$slash$user_id';
final res = await this.httpClient.get(usersDetailUrl);
if (res.statusCode != 200) {
throw Exception('error getting weather for location');
}
final employeeDetailJson = jsonDecode(res.body);
return UserDetailResponse.fromJson(employeeDetailJson).data;
}
}
import 'package:flutter_sample_api_bloc/model/user_data.dart';
import 'package:flutter_sample_api_bloc/model/user_detail.dart';
import 'package:flutter_sample_api_bloc/repository/sample_api_client.dart';
import 'package:meta/meta.dart';
class UserRepository {
final EmployeeApiClient employeeApiClient;
UserRepository({@required this.employeeApiClient})
: assert(employeeApiClient != null);
Future<List<User>> getAllUsers() async {
return employeeApiClient.getAllUser( );
}
Future<UserDetail> getUserDetails(int id) async {
return employeeApiClient.getUserDetail( id );
}
}
import 'dart:async';
import 'package:flutter_sample_api_bloc/model/user_data.dart';
import 'package:flutter_sample_api_bloc/repository/sample_api_repository.dart';
import 'package:meta/meta.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
///Event class
abstract class UserEvent extends Equatable {
const UserEvent();
}
class FetchUserEvent extends UserEvent {
const FetchUserEvent() ;
@override
List<Object> get props => [];
}
class RefreshUserEvent extends UserEvent {
const RefreshUserEvent();
@override
List<Object> get props => [];
}
///State Class
abstract class UserState extends Equatable {
const UserState();
@override
List<Object> get props => [];
}
class UserEmpty extends UserState {}
class UserLoading extends UserState {}
class UserLoaded extends UserState {
final List<User> users;
const UserLoaded({@required this.users}) : assert(users != null);
@override
List<Object> get props => [users];
}
class UserError extends UserState {
}
class UserBloc extends Bloc<UserEvent, UserState> {
final UserRepository employeeRepository;
UserBloc({@required this.employeeRepository})
: assert(employeeRepository != null);
@override
UserState get initialState => UserEmpty();
@override
Stream<UserState> mapEventToState(UserEvent event) async* {
if (event is FetchUserEvent) {
yield UserLoading();
try {
final List<User> employees = await employeeRepository.getAllUsers();
yield UserLoaded(users: employees);
} catch (_) {
yield UserError();
}
}
if (event is RefreshUserEvent) {
yield UserLoading();
try {
final List<User> employees = await employeeRepository.getAllUsers();
yield UserLoaded(users: employees);
} catch (_) {
yield UserError();
}
}
}
}
class UserResponse {
int page;
int perPage;
int total;
int totalPages;
List<User> user;
UserResponse(
{this.page, this.perPage, this.total, this.totalPages, this.user});
UserResponse.fromJson(Map<String, dynamic> json) {
page = json['page'];
perPage = json['per_page'];
total = json['total'];
totalPages = json['total_pages'];
if (json['data'] != null) {
user = new List<User>();
json['data'].forEach((v) {
user.add(new User.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['page'] = this.page;
data['per_page'] = this.perPage;
data['total'] = this.total;
data['total_pages'] = this.totalPages;
if (this.user != null) {
data['data'] = this.user.map((v) => v.toJson()).toList();
}
return data;
}
}
class User {
int id;
String email;
String firstName;
String lastName;
String avatar;
User({this.id, this.email, this.firstName, this.lastName, this.avatar});
User.fromJson(Map<String, dynamic> json) {
id = json['id'];
email = json['email'];
firstName = json['first_name'];
lastName = json['last_name'];
avatar = json['avatar'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['email'] = this.email;
data['first_name'] = this.firstName;
data['last_name'] = this.lastName;
data['avatar'] = this.avatar;
return data;
}
}
class UserDetailResponse {
UserDetail data;
UserDetailResponse({this.data});
UserDetailResponse.fromJson(Map<String, dynamic> json) {
data = json['data'] != null ? new UserDetail.fromJson(json['data']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.data != null) {
data['data'] = this.data.toJson();
}
return data;
}
}
class UserDetail {
int id;
String email;
String firstName;
String lastName;
String avatar;
UserDetail({this.id, this.email, this.firstName, this.lastName, this.avatar});
UserDetail.fromJson(Map<String, dynamic> json) {
id = json['id'];
email = json['email'];
firstName = json['first_name'];
lastName = json['last_name'];
avatar = json['avatar'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['email'] = this.email;
data['first_name'] = this.firstName;
data['last_name'] = this.lastName;
data['avatar'] = this.avatar;
return data;
}
}
import 'dart:async';
import 'package:flutter_sample_api_bloc/model/user_detail.dart';
import 'package:flutter_sample_api_bloc/repository/sample_api_repository.dart';
import 'package:meta/meta.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
///Event class
abstract class UserDetailEvent extends Equatable {
const UserDetailEvent();
}
class FetchUserDetailEvent extends UserDetailEvent {
final int id;
const FetchUserDetailEvent({@required this.id}) : assert(id != null);
@override
List<Object> get props => [id];
}
class RefreshUserDetailEvent extends UserDetailEvent {
final int id;
const RefreshUserDetailEvent({@required this.id}) : assert(id != null);
@override
List<Object> get props => [id];
}
///State Class
abstract class UserDetailState extends Equatable {
const UserDetailState();
@override
List<Object> get props => [];
}
class UserDetailEmpty extends UserDetailState {}
class UserDetailLoading extends UserDetailState {}
class UserDetailLoaded extends UserDetailState {
final UserDetail userDetail;
const UserDetailLoaded({@required this.userDetail}) : assert(userDetail != null);
@override
List<Object> get props => [userDetail];
}
class UserDetailError extends UserDetailState {
}
class UserDetailBloc extends Bloc<UserDetailEvent, UserDetailState> {
final UserRepository userRepository;
UserDetailBloc({@required this.userRepository})
: assert(userRepository != null);
@override
UserDetailState get initialState => UserDetailEmpty();
@override
Stream<UserDetailState> mapEventToState(UserDetailEvent event) async* {
if (event is FetchUserDetailEvent) {
yield UserDetailLoading();
try {
final UserDetail employees = await userRepository.getUserDetails(event.id);
yield UserDetailLoaded(userDetail: employees);
} catch (_) {
yield UserDetailError();
}
}
if (event is RefreshUserDetailEvent) {
yield UserDetailLoading();
try {
final UserDetail employees = await userRepository.getUserDetails(event.id);
yield UserDetailLoaded(userDetail: employees);
} catch (_) {
yield UserDetailError();
}
}
}
}
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_sample_api_bloc/bloc/user_detail_bloc.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
class UserDetailView extends StatelessWidget {
final int id;
Completer<void> _refreshCompleter;
final RefreshController _refreshController = RefreshController( );
@override
void initState() {
_refreshCompleter = Completer<void>( );
}
UserDetailView({@required this.id}) : assert(id != null);
@override
Widget build(BuildContext context) {
final UserDetailBloc employeeDetailBloc = BlocProvider.of<UserDetailBloc>(context);
return MaterialApp(
home: Scaffold(
appBar: AppBar(
// backgroundColor: Colors.red,
title: new Text(
"Employee Detail",
),
elevation: 4.0,
),
body: BlocBuilder(bloc:employeeDetailBloc,builder: (context, state) {
return SmartRefresher(
controller: _refreshController,
enablePullDown: true,
child: setList(state),
onRefresh: () async {
BlocProvider.of<UserDetailBloc>( context ).add(
RefreshUserDetailEvent( id: id ) );
_refreshCompleter?.complete( );
_refreshCompleter = Completer( );
}
);
}
),
),
);
}
}
Widget setList(UserDetailState state) {
if (state is UserDetailLoading) {
return Center( child: CircularProgressIndicator( ) );
}
if (state is UserDetailLoaded) {
return ListView(
children: <Widget>[
ListTile(
leading: Icon( Icons.wb_sunny ),
title: Text( state.userDetail.email ),
trailing: Icon( Icons.keyboard_arrow_right ),
),
ListTile(
leading: Icon( Icons.brightness_3 ),
title: Text( state.userDetail.firstName ),
trailing: Icon( Icons.keyboard_arrow_right )
),
ListTile(
leading: Icon( Icons.star ),
title: Text( state.userDetail.lastName ),
trailing: Icon( Icons.keyboard_arrow_right )
),
],
);
}
if (state is UserDetailError) {
return Text(
'Something went wrong!',
style: TextStyle( color: Colors.red ),
);
}
return Center( child: Text( 'Pull refresh to get employee..! ' ) );
}
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_sample_api_bloc/bloc/user_bloc.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'user_detail_view.dart';
class UserView extends StatelessWidget {
Completer<void> _refreshCompleter;
@override
void initState() {
_refreshCompleter = Completer<void>();
}
final RefreshController _refreshController = RefreshController( );
@override
Widget build(BuildContext context) {
return BlocListener<UserBloc, UserState>(
listener: (context, state) {
if (state is UserLoaded) {
}
},
child: BlocBuilder<UserBloc, UserState>(
builder: (context, state) {
return SmartRefresher(
controller: _refreshController,
enablePullDown: true,
onRefresh: () async {
BlocProvider.of<UserBloc>( context ).add(RefreshUserEvent());
_refreshCompleter?.complete();
_refreshCompleter = Completer();
},
child: setList(state));
}
)
);
}
Widget setList(UserState state) {
if (state is UserLoading) {
return Center( child: CircularProgressIndicator( ) );
}
if (state is UserLoaded) {
_refreshController.refreshCompleted();
return
ListView.builder(
itemCount: state.users.length,
itemBuilder: (context, index) {
return ListTile(
leading: Icon( Icons.face),
title: Text( state.users[index].firstName ),
trailing: GestureDetector(child: Icon( Icons.keyboard_arrow_right ),
onTap:(){
int id = state.users[index].id;
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) {
return UserDetailView(id:id);
},
),
);
},
),
);
},
);
}
if (state is UserError) {
return Text(
'Something went wrong!',
style: TextStyle( color: Colors.red ),
);
}
return Center( child: Text( 'Pull refresh to get employee..! ' ) );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment