I am encountering a problem with the PagingController
logic when using it within a GetX controller. Specifically, after invoking pagingController.fetchNextPage()
for the first time, the _isFetching
flag in PagingController
remains permanently set to TRUE
.
Also when fetchNextPage
is called for the first time the listener does listen but it reads controllers.loadedItems as empty
PS: We need to use GetX (get | Flutter package) and not Provider and Consumer
Here’s a detailed breakdown of the issue:
- Problem Description: Upon calling
pagingController.fetchNextPage()
, the execution appears to hang at the following line without throwing an error or returning any data:
final data = await pageFuture(_nextPageToken);
The _isFetching
variable does not revert to FALSE
, which seems to indicate that the fetch process never completes.
- Context: This issue only occurs when the logic is implemented in a GetX controller. The same logic functions correctly within a stateful widget class. Our application requires using a controller because the fetched data is utilized across multiple screens.
- Request: Could you please advise on potential causes or solutions for this behavior? It appears that the asynchronous fetch operation does not conclude properly within the GetX controller context.
Attached below is the relevant section of my album_controller
class for your review. Your insights on resolving this issue would be greatly appreciated, as it is crucial for the data to be shared across various parts of our application.
AlbumController Class BELOW
import 'package:app/logger.dart';
import 'package:app/objects/fam_image.dart';
import 'package:app/screens/home/album_screen.dart';
import 'package:app/services/amity/user_service.dart';
import 'package:app/services/lock_time_service.dart';
import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'package:amity_sdk/amity_sdk.dart';
import 'package:shared_preferences/shared_preferences.dart';
class AlbumController extends GetxController {
final ScrollController scrollController = ScrollController();
RxBool showSelectButton = false.obs;
RxList<FamImage> lockedFamImages = <FamImage>[].obs;
RxList<FamImage> unlockedFamImages = <FamImage>[].obs;
RxList<AmityPost> lockedPosts = <AmityPost>[].obs;
RxList<AmityPost> unlockedPosts = <AmityPost>[].obs;
late PagingController<AmityPost> controller;
final userService = Get.find<UserService>();
final locktimeService = Get.find<LockTimeService>();
RxBool unlockPhotoExists = false.obs;
RxBool hasUnlockPhotoOnce = false.obs;
@override
void onInit() {
super.onInit();
//? Initialize the page controller to retrieve posts from Amity
initializePageController().then((value) {
controller.fetchNextPage();
});
checkUnlockPhotoOnce().then((hasUnlocked) {
showSelectButton.value = hasUnlocked;
});
getUnlockPhotoExistsSharedPreference().then((value) {
unlockPhotoExists.value = value;
});
//? Check if the user have unlocked photos atleast once
checkUnlockPhotoOnce().then((value) {
hasUnlockPhotoOnce.value = value;
});
}
@override
void onClose() {
scrollController.dispose();
controller.dispose();
super.onClose();
}
Future<void> initializePageController({bool isForce = false}) async {
if (isForce) {
lockedFamImages.clear();
unlockedFamImages.clear();
lockedPosts.clear();
unlockedPosts.clear();
controller.dispose();
}
controller = PagingController(
pageFuture: (token) => AmitySocialClient.newFeedRepository()
.getGlobalFeed()
.getPagingData(token: token, limit: 20),
pageSize: 20,
);
controller.addListener(
() {
AppLogger.logInfo('Listener called: Album Controller');
//? Listener is called once after fetchNextPage and loadedItems is empty when there are actually datas in amity
for (AmityPost amityPost in controller.loadedItems) {
//OUR APP LISTENER LOGIC
}
},
);
if (isForce) {
// After reinitializing the controller, fetch the next page immediately
controller.fetchNextPage();
}
}
Future<bool> loadMoreGlobalFeed({bool isForce = false}) async {
if (controller.hasMoreItems || isForce) {
lockedPosts.clear();
unlockedPosts.clear();
controller.fetchNextPage();
return true;
} else {
return false;
}
}
Future<bool> checkUnlockPhotoOnce() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getBool('checkUnlockPhotoOnce') ?? false;
}
}