@@ -5,13 +5,35 @@ import '../../../instance_manager.dart';
5
5
import '../rx_flutter/rx_notifier.dart' ;
6
6
import 'list_notifier.dart' ;
7
7
8
+ /// A base controller class that provides state management functionality.
9
+ ///
10
+ /// Extend this class to create a controller that can be used with GetX's
11
+ /// state management system. This class provides methods to update the UI
12
+ /// when the controller's state changes.
13
+ ///
14
+ /// Example:
15
+ /// ```dart
16
+ /// class CounterController extends GetxController {
17
+ /// var count = 0;
18
+ ///
19
+ /// void increment() {
20
+ /// count++;
21
+ /// update(); // Triggers UI update
22
+ /// }
23
+ /// }
24
+ /// ```
8
25
// ignore: prefer_mixin
9
26
abstract class GetxController extends ListNotifier with GetLifeCycleMixin {
10
- /// Rebuilds `GetBuilder` each time you call `update()` ;
11
- /// Can take a List of [ids] , that will only update the matching
12
- /// `GetBuilder( id: )` ,
13
- /// [ids] can be reused among `GetBuilders` like group tags.
14
- /// The update will only notify the Widgets, if [condition] is true.
27
+ /// Notifies listeners to update the UI.
28
+ ///
29
+ /// When called without parameters, it will update all widgets that depend on
30
+ /// this controller. You can also specify specific widget IDs to update only
31
+ /// those widgets.
32
+ ///
33
+ /// Parameters:
34
+ /// - [ids] : Optional list of widget IDs to update. If null, updates all widgets.
35
+ /// - [condition] : If false, the update will be skipped.
36
+ ///
15
37
void update ([List <Object >? ids, bool condition = true ]) {
16
38
if (! condition) {
17
39
return ;
@@ -26,9 +48,27 @@ abstract class GetxController extends ListNotifier with GetLifeCycleMixin {
26
48
}
27
49
}
28
50
29
- /// this mixin allow to fetch data when the scroll is at the bottom or on the
30
- /// top
51
+ /// A mixin that provides scroll-based data fetching capabilities.
52
+ ///
53
+ /// This mixin can be used with controllers that need to load more data
54
+ /// when the user scrolls to the top or bottom of a scrollable view.
55
+ ///
56
+ /// Example:
57
+ /// ```dart
58
+ /// class MyController extends GetxController with ScrollMixin {
59
+ /// @override
60
+ /// Future<void> onEndScroll() async {
61
+ /// // Load more data when scrolled to bottom
62
+ /// }
63
+ ///
64
+ /// @override
65
+ /// Future<void> onTopScroll() async {
66
+ /// // Load previous data when scrolled to top
67
+ /// }
68
+ /// }
69
+ /// ```
31
70
mixin ScrollMixin on GetLifeCycleMixin {
71
+ /// The scroll controller used to detect scroll position
32
72
final ScrollController scroll = ScrollController ();
33
73
34
74
@override
@@ -37,8 +77,10 @@ mixin ScrollMixin on GetLifeCycleMixin {
37
77
scroll.addListener (_listener);
38
78
}
39
79
80
+ /// Flag to prevent multiple simultaneous bottom fetches
40
81
bool _canFetchBottom = true ;
41
82
83
+ /// Flag to prevent multiple simultaneous top fetches
42
84
bool _canFetchTop = true ;
43
85
44
86
void _listener () {
@@ -70,27 +112,137 @@ mixin ScrollMixin on GetLifeCycleMixin {
70
112
@override
71
113
void onClose () {
72
114
scroll.removeListener (_listener);
115
+ scroll.dispose ();
73
116
super .onClose ();
74
117
}
75
118
}
76
119
77
- /// A clean controller to be used with only Rx variables
120
+ /// A base controller class for reactive state management using Rx variables.
121
+ ///
122
+ /// This class is a lightweight alternative to [GetxController] when you only
123
+ /// need reactive variables without the need for manual UI updates.
124
+ ///
125
+ /// Example:
126
+ /// ```dart
127
+ /// class UserController extends RxController {
128
+ /// final name = 'John'.obs;
129
+ /// final age = 30.obs;
130
+ /// }
131
+ /// ```
78
132
abstract class RxController with GetLifeCycleMixin {}
79
133
80
- /// A recommended way to use Getx with Future fetching
134
+ /// A controller that manages state for asynchronous operations.
135
+ ///
136
+ /// This controller provides a standard way to handle loading, error, and success
137
+ /// states for async operations. It's particularly useful for API calls and
138
+ /// other asynchronous operations.
139
+ ///
140
+ /// Type parameters:
141
+ /// - [T] : The type of data this controller will manage
142
+ ///
143
+ /// Example:
144
+ /// ```dart
145
+ /// class UserController extends StateController<User> {
146
+ /// Future<void> fetchUser() async {
147
+ /// change(null, status: RxStatus.loading());
148
+ /// try {
149
+ /// final user = await userRepository.getUser();
150
+ /// change(user, status: RxStatus.success());
151
+ /// } catch (e) {
152
+ /// change(state, status: RxStatus.error(e.toString()));
153
+ /// }
154
+ /// }
155
+ /// }
156
+ /// ```
81
157
abstract class StateController <T > extends GetxController with StateMixin <T > {}
82
158
83
- /// A controller with super lifecycles (including native lifecycles)
84
- /// and StateMixins
159
+ /// A controller that combines full lifecycle management with state management.
160
+ ///
161
+ /// This controller is ideal for complex scenarios where you need both:
162
+ /// 1. Full app lifecycle awareness
163
+ /// 2. State management with loading/error states
164
+ ///
165
+ /// Type parameters:
166
+ /// - [T] : The type of data this controller will manage
167
+ ///
168
+ /// Example:
169
+ /// ```dart
170
+ /// class HomeController extends SuperController<HomeState> {
171
+ /// @override
172
+ /// void onResumed() {
173
+ /// // App came to foreground
174
+ /// fetchData();
175
+ /// }
176
+ ///
177
+ /// Future<void> fetchData() async {
178
+ /// change(state, status: RxStatus.loading());
179
+ /// try {
180
+ /// final data = await repository.getData();
181
+ /// change(HomeState(data: data), status: RxStatus.success());
182
+ /// } catch (e) {
183
+ /// change(state, status: RxStatus.error(e.toString()));
184
+ /// }
185
+ /// }
186
+ /// }
187
+ /// ```
85
188
abstract class SuperController <T > extends FullLifeCycleController
86
189
with FullLifeCycleMixin , StateMixin <T > {}
87
190
88
- /// A controller with super lifecycles (including native lifecycles)
191
+ /// A controller that can observe the full app lifecycle.
192
+ ///
193
+ /// This controller extends [GetxController] and implements [WidgetsBindingObserver]
194
+ /// to provide full lifecycle awareness. It can respond to:
195
+ /// - App lifecycle changes (resumed, paused, etc.)
196
+ /// - Memory pressure events
197
+ /// - Accessibility changes
198
+ ///
199
+ /// Note: Don't forget to call `super.onClose()` in your controller's
200
+ /// [onClose] method to properly clean up the observer.
201
+ ///
202
+ /// Example:
203
+ /// ```dart
204
+ /// class MyController extends FullLifeCycleController {
205
+ /// @override
206
+ /// void onResumed() {
207
+ /// // App came to foreground
208
+ /// }
209
+ ///
210
+ /// @override
211
+ /// void onPaused() {
212
+ /// // App went to background
213
+ /// }
214
+ ///
215
+ /// @override
216
+ /// void onClose() {
217
+ /// // Clean up resources
218
+ /// super.onClose();
219
+ /// }
220
+ /// }
221
+ /// ```
89
222
abstract class FullLifeCycleController extends GetxController
90
223
with
91
224
// ignore: prefer_mixin
92
225
WidgetsBindingObserver {}
93
226
227
+ /// A mixin that provides full lifecycle callbacks for the controller.
228
+ ///
229
+ /// This mixin handles app lifecycle events, memory pressure, and accessibility changes.
230
+ /// Override the provided methods to respond to these events.
231
+ ///
232
+ /// Example:
233
+ /// ```dart
234
+ /// class MyController extends FullLifeCycleController with FullLifeCycleMixin {
235
+ /// @override
236
+ /// void onResumed() {
237
+ /// // App came to foreground
238
+ /// }
239
+ ///
240
+ /// @override
241
+ /// void onMemoryPressure() {
242
+ /// // Clean up resources when system is low on memory
243
+ /// }
244
+ /// }
245
+ /// ```
94
246
mixin FullLifeCycleMixin on FullLifeCycleController {
95
247
@mustCallSuper
96
248
@override
@@ -128,9 +280,44 @@ mixin FullLifeCycleMixin on FullLifeCycleController {
128
280
}
129
281
}
130
282
283
+ @override
284
+ void didHaveMemoryPressure () {
285
+ super .didHaveMemoryPressure ();
286
+ onMemoryPressure ();
287
+ }
288
+
289
+ @override
290
+ void didChangeAccessibilityFeatures () {
291
+ super .didChangeAccessibilityFeatures ();
292
+ onAccessibilityChanged ();
293
+ }
294
+
295
+ /// Called when the system reports that the app is visible and interactive.
296
+ /// This is called when the app returns to the foreground.
131
297
void onResumed () {}
298
+
299
+ /// Called when the app is not currently visible to the user, not responding to
300
+ /// user input, and running in the background.
132
301
void onPaused () {}
302
+
303
+ /// Called when the app is in an inactive state and is not receiving user input.
304
+ /// For example, when a phone call is received or when the app is in a
305
+ /// multi-window mode.
133
306
void onInactive () {}
307
+
308
+ /// Called before the app is destroyed.
309
+ /// This is the final callback the app will receive before it is terminated.
134
310
void onDetached () {}
311
+
312
+ /// Called when the app is hidden (e.g., when the device is locked).
135
313
void onHidden () {}
314
+
315
+ /// Called when the system is running low on memory.
316
+ /// Override this method to release caches or other resources that aren't
317
+ /// critical for the app to function.
318
+ void onMemoryPressure () {}
319
+
320
+ /// Called when the system changes the set of currently active accessibility
321
+ /// features.
322
+ void onAccessibilityChanged () {}
136
323
}
0 commit comments