To implement a character list page following the MobX pattern in this project, you should separate the page into three distinct parts: a StatelessWidget for dependency injection, a StatefulWidget (View) for lifecycle management, and a private StatefulWidget (Content) for UI rendering and scroll handling.
- Dependency Injection: Use a
StatelessWidget to instantiate the CharacterPageStore, passing in required domain use cases (e.g., GetAllCharacters) retrieved via context.read(). - Lifecycle Management: Use a
StatefulWidget to trigger initial data fetching in initState using WidgetsBinding.instance.addPostFrameCallback to ensure the store's fetchNextPage() is called after the first frame. - Reactive UI: Wrap the UI in an
Observer widget from flutter_mobx. Use the store's contentStatus to toggle between a loading indicator and the main content. - Pagination: Implement infinite scrolling by attaching a
ScrollController to a ListView.builder. When the user scrolls near the bottom (e.g., 90% of the way), call store.fetchNextPage().
Note: The store's charactersList and hasReachedEnd properties should drive the list length and the visibility of loading indicators at the end of the list.
// 1. The Entry Point (Dependency Injection)
class CharacterPage extends StatelessWidget {
const CharacterPage({super.key});
@override
Widget build(BuildContext context) {
return CharacterView(
store: CharacterPageStore(
getAllCharacters: context.read<GetAllCharacters>(),
),
);
}
}
// 2. The View (Lifecycle)
class CharacterView extends StatefulWidget {
const CharacterView({super.key, required this.store});
final CharacterPageStore store;
@override
State<CharacterView> createState() => _CharacterViewState();
}
class _CharacterViewState extends State<CharacterView> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
widget.store.fetchNextPage();
});
}
@override
Widget build(BuildContext context) {
return Observer(
builder: (_) => widget.store.contentStatus == CharacterPageStatus.loading
? const Center(child: CircularProgressIndicator())
: _Content(store: widget.store),
);
}
}