Pagination with Bloc Pattern in Flutter
import "package:flutter/material.dart";
import "package:flutter_bloc/flutter_bloc.dart";
import "package:pagination_practice/Pagination_with_Bloc/Bloc/bloc.dart";
import "package:pagination_practice/Pagination_with_Bloc/Bloc/event.dart";
import "package:pagination_practice/Pagination_with_Bloc/Bloc/state.dart";
import "package:pagination_practice/Pagination_with_Bloc/post_repo.dart";
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return RepositoryProvider<PostRepo>(
create: (context) => PostRepo(),
child: BlocProvider<PostBloc>(
create: (context) =>
PostBloc(context.read<PostRepo>())..add(FetchPostsEvent()),
child: MaterialApp(
title: "Pagination",
debugShowCheckedModeBanner: false,
theme: ThemeData(
appBarTheme: const AppBarTheme(
backgroundColor: Colors.grey,
centerTitle: true,
),
),
home: const PostUi(),
),
),
);
}
}
class PostUi extends StatelessWidget {
const PostUi({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: BlocBuilder<PostBloc, PostsBlocState>(
builder: (context, state) {
if (state is PostBlocLoadingState) {
return const Center(
child: CircularProgressIndicator(),
);
} else if (state is PostBlocSuccessState) {
var posts = state.posts;
return ListView.builder(
controller: context.read<PostBloc>().scrollController,
itemCount: context.read<PostBloc>().isLoadingMore
? posts.length + 1
: posts.length,
itemBuilder: (context, index) {
if (index >= posts.length) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
var post = posts[index];
return Card(
child: ListTile(
leading: CircleAvatar(
child: Text("$index"),
),
title: Text(
post["id"].toString(),
style: const TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(post["title"]["rendered"].toString()),
),
);
}
},
);
} else {
return Container();
}
},
),
);
}
}
import "dart:convert";
import "package:http/http.dart" as http;
class PostRepo {
fetchPosts(int page) async {
final url = Uri.parse(
"https://techcrunch.com/wp-json/wp/v2/posts?%22%22context=embed&per_page=20&page=$page");
var response = await http.get(url);
if (response.statusCode == 200) {
var json = jsonDecode(response.body) as List;
return json;
}
}
}
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pagination_practice/Pagination_with_Bloc/Bloc/event.dart';
import 'package:pagination_practice/Pagination_with_Bloc/Bloc/state.dart';
import 'package:pagination_practice/Pagination_with_Bloc/post_repo.dart';
class PostBloc extends Bloc<PostEvent, PostsBlocState> {
int page = 1;
ScrollController scrollController = ScrollController();
bool isLoadingMore = false;
PostRepo repo;
PostBloc(this.repo) : super(InitBlocState(null)) {
scrollController.addListener(
() {
add(LoadMoreEvent());
},
);
on<FetchPostsEvent>(
(event, emit) async {
emit(PostBlocLoadingState(null));
var posts = await repo.fetchPosts(page);
emit(PostBlocSuccessState(posts: posts));
},
);
on<LoadMoreEvent>(
(event, emit) async {
if (scrollController.position.pixels ==
scrollController.position.maxScrollExtent) {
isLoadingMore = true;
page++;
var posts = await repo.fetchPosts(page);
emit(PostBlocSuccessState(posts: [...state.posts, ...posts]));
}
},
);
}
}
abstract class PostEvent {}
class FetchPostsEvent extends PostEvent {}
class LoadMoreEvent extends PostEvent {}
abstract class PostsBlocState {
final posts;
PostsBlocState(this.posts);
}
class InitBlocState extends PostsBlocState {
InitBlocState(super.posts);
}
class PostBlocLoadingState extends PostsBlocState {
PostBlocLoadingState(super.posts);
}
class PostBlocSuccessState extends PostsBlocState {
PostBlocSuccessState({required posts}) : super(posts);
}
Comments
Post a Comment