infinite scrolling from flutter application that fetches data from WordPress rest API based on categories... I tried to fetch data based on categories but it display all data on all categories tabs ... I just want to know how to filter news in their category it was working fine before I try to add infinite scrolling
Categories List are loading in all the tabs but the problem is when changing tabs, previous tab category list data is loading on the top of the next tab. How to overcome this problem. First tab data is loading when changing to the second tab on the top and In third tab First tab and Second tab data is loading on the top.
this is config.dart
class Config {
static String? apiURL = "https://hageez.tech/wp-json/wp/v2/";
static String? categoryURl = "categories?per_page=100";
static String? postURL = "latest-posts/?page_size=3&category_id=";
static String? postDetailURL = 'post-details/?id=';
static String? dateFormat = "dd-MM-yyyy";
}
this is API fetch for post and categories
class APIService {
static var client = http.Client();
static Future<List<CategoryModel>?> fetchCategories() async {
var response =
await client.get(Uri.parse(Config.apiURL! +
Config.categoryURl!));
if (response.statusCode == 200) {
var jsonString = response.body;
return categoryFromJson(jsonString);
} else {
return null;
}
}
static Future<List<NewsModel>?> fetchPosts(
int categoryId,
int pageNumber,
) async {
var url = Config.apiURL! +
Config.postURL! +
categoryId.toString() +
"&page_no=" +
pageNumber.toString();
var response = await client.get(Uri.parse(url));
if (response.statusCode == 200) {
var jsonString = response.body;
return postsFromJson(jsonString);
}
return null;
}
this is controller part using getx for category and post
class CategoriesController extends GetxController
with GetSingleTickerProviderStateMixin {
var isloading = true.obs;
var categoriesList = <CategoryModel>[].obs;
@override
void onInit() {
// TODO: implement onInit
fetchCategories();
super.onInit();
}
Future<void> fetchCategories() async {
try {
isloading(true);
var categories = await APIService.fetchCategories();
if (categories!.length > 0) {
categoriesList.clear();
categoriesList.addAll(categories);
}
} finally {
isloading(false);
}
}
}
this is postcontroller
class postcontroller extends GetxController {
var isloading = true.obs;
var postList = <NewsModel>[].obs;
@override
void onInit() {
// TODO: implement onInit
fetchPosts();
super.onInit();
}
Future<void> fetchPosts(
{int categoryId = 1, int pageNumber = 0, int totalrecords = 0}) async {
try {
if (postList.length == 0 || pageNumber == 0) {
isloading(true);
postList.clear();
}
if (postList.length < totalrecords) {
var posts = await APIService.fetchPosts( categoryId,pageNumber,);
if (posts != null) {
postList.addAll(posts);
print(posts);
}
}
} finally {
isloading(false);
}
}
}
the following is postpage that have tabs based on categories and for the post inject data from newspage.dart
class trytab extends StatefulWidget {
trytab({Key? key}) : super(key: key);
@override
State<trytab> createState() => _trytabState();
}
class _trytabState extends State<trytab> with SingleTickerProviderStateMixin {
final CategoriesController categoriesController =
Get.put(CategoriesController());
// List<Widget> tabs =[];
@override
void initState() {
// TODO: implement initState
super.initState();
// tabs.add(tab("tabName"));
// tabs.add(tab(" hey brother "));
// tabs.add(tab("3"));
// tabs.add(tab("5"));
// tabs.add(tab("tab6Name"));
}
@override
Widget build(BuildContext context) {
return Center(
child: Obx(() {
return DefaultTabController(
length: categoriesController.categoriesList.length,
child: Scaffold(
appBar: AppBar(
title: Text("API TEST"),
bottom: TabBar(
isScrollable: true,
tabs:categoriesController.categoriesList
.map((model) => tab(model.categoryName))
.toList()),
),
body: TabBarView(
children: categoriesController.categoriesList.map((model) {
return newspage(
categoryID: model.categoryId,
isRelod: true,
totalRecords: model.count,
);
}).toList(),
),
),
);
}),
);
}
}
newspge.dart
class newspage extends StatefulWidget {
late int? categoryID;
late bool? isRelod;
late int? totalRecords;
newspage({this.categoryID, this.isRelod, this.totalRecords});
@override
State<newspage> createState() => _newspageState();
}
class _newspageState extends State<newspage> {
final postcontroller postController = Get.put(postcontroller());
var refreshkey = GlobalKey<RefreshIndicatorState>();
ScrollController _scrollController = new ScrollController();
int _page = 1;
@override
void initState() {
// TODO: implement initState
super.initState();
Future.delayed(Duration.zero, () async {
if (this.widget.isRelod!) {
await postController.fetchPosts(
categoryId: this.widget.categoryID!,
pageNumber: 1,
totalrecords: this.widget.totalRecords!);
}
});
_scrollController.addListener(() async {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
await postController.fetchPosts(
categoryId: this.widget.categoryID!,
pageNumber: ++_page,
totalrecords: this.widget.totalRecords!,
);
}
});
}
@override
Widget build(BuildContext context) {
return newslist();
}
Widget newslist() {
return Container(
child: Obx(() {
if (postController.isloading.value) {
return Center(
child: CircularProgressIndicator(),
);
}
// ignore: curly_braces_in_flow_control_structures
else
// ignore: curly_braces_in_flow_control_structures
return RefreshIndicator(
child: ListView.builder(
key: refreshkey,
physics: const AlwaysScrollableScrollPhysics(),
itemCount: postController.postList.length,
controller: _scrollController,
itemBuilder: (context, index) {
if ((index == postController.postList.length - 1) &&
postController.postList.length <
this.widget.totalRecords!) {
return Center(child: CircularProgressIndicator());
}
return newsbycategory(
model: postController.postList[index]);
}),
onRefresh: () => postController.fetchPosts(
categoryId: this.widget.categoryID!,
pageNumber: ++_page,
totalrecords: this.widget.totalRecords!));
}),
);
}
}