Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
preface
Most pages of App will involve data loading, error, no data and normal states. At the beginning, we may enumerate the states of data acquisition using if… Else or switch displays the different widgets, which makes the code look ugly, like this:
if (PersonalController.to.loadingStatus == LoadingStatus.loading) {
return Center(
child: Text('Loading... ')); }if (PersonalController.to.loadingStatus == LoadingStatus.failed) {
return Center(
child: Text('Request failed')); }// Normal status
PersonalEntity personalProfile = PersonalController.to.personalProfile;
returnStack( ... ) ;Copy the code
This situation is so inelegant that GetX provides a StateMixin solution to this problem.
StateMixin
StateMixin is a mixin defined by GetX, which can mix the page data loading state with the state data, including the following states:
RxStatus.loading()
: loading;RxStatus.success()
: Loading succeeded.RxStatus.error([String? message])
: Load failed, may carry an error messagemessage
;RxStatus.empty()
: No data is available.
StateMixin can be used as follows:
class XXXController extends GetxController
with StateMixin<T> {}Copy the code
Where T is the actual state class, such as PersonalEntity in our previous article, which can be defined as:
class PersonalMixinController extends GetxController
with StateMixin<PersonalEntity> {}Copy the code
StateMixin then provides a change method to pass state data and state to the page.
void change(T? newState, {RxStatus? status})
Copy the code
Where newState is the newState data, status is the four states mentioned above. This method notifies the Widget to refresh.
GetView
GetX provides a quick Widget to access the Controller in the container, GetView. GetView is an abstract class that inherits the StatelessWidget. The implementation is simple, except that it defines a get property to get the Controller.
abstract class GetView<T> extends StatelessWidget {
const GetView({Key? key}) : super(key: key);
final String? tag = null;
T getcontroller => GetInstance().find<T>(tag: tag)! ;@override
Widget build(BuildContext context);
}
Copy the code
By inheriting GetView, you can directly build the interface using Controller.obx. The controller. Obx feature is that four properties are defined for each of the four states of RxStatus:
Widget obx( NotifierBuilder<T? > widget, { WidgetFunction(String? error)? onError,
Widget? onLoading,
Widget? onEmpty,
})
Copy the code
- NotifierBuilder
?>
Widget: a function that returns the normal status interface with a status variable, NotifierBuilder
?>
is defined as follows. This way you can use state variables to build a normal interface.
typedef NotifierBuilder<T> = Widget Function(T state);
Copy the code
onError
: Corresponds to an errorWidget
Build functions that can use error messageserror
.onLoading
: Corresponds to the loading timeWidget
;onEmpty
: Indicates that the data is nullWidget
.
In this way, you can automatically build different state UI interfaces based on the RxStatus specified by the change method, thus avoiding ugly if… Else or switch statements. For example, our personal home page, can be written according to the following way, is not the feeling more clear and refreshing?
class PersonalHomePageMixin extends GetView<PersonalMixinController> {
PersonalHomePageMixin({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
returncontroller.obx( (personalEntity) => _PersonalHomePage(personalProfile: personalEntity!) , onLoading: Center( child: CircularProgressIndicator(), ), onError: (error) => Center( child: Text(error!) , ), onEmpty: Center( child: Text('No data at present'),),); }}Copy the code
The code for the corresponding PersonalMixinController is as follows:
class PersonalMixinController extends GetxController
with StateMixin<PersonalEntity> {
final String userId;
PersonalMixinController({required this.userId});
@override
void onReady() {
getPersonalProfile(userId);
super.onReady();
}
void getPersonalProfile(String userId) async {
change(null, status: RxStatus.loading());
var personalProfile = await JuejinService().getPersonalProfile(userId);
if(personalProfile ! =null) {
change(personalProfile, status: RxStatus.success());
} else {
change(null, status: RxStatus.error('Failed to obtain personal information')); }}}Copy the code
The construction of the Controller
From GetView source code as you can see, the Controller is to get the container, it will need to use the GetX container, registered before using the Controller to GetX container.
Get.lazyPut<PersonalMixinController>(
() => PersonalMixinController(userId: '70787819648695'));Copy the code
conclusion
This article describes how to use GetX’s StateMixin approach to build a more elegant page structure, using controller.obx parameters to configure different states for different components. Components can be switched automatically based on the RxStatus status without having to write ugly if… Else or switch statements. Of course, the premise of using this method is to build the Controller object in the container of GetX, this source has been uploaded to: GetX state management source code. In fact, there are other benefits to using containers. A typical application is Dependency Injection (DI). In the next two articles, we will introduce the concept and application of DI.
I am dao Code Farmer with the same name as my wechat official account. This is a column about the introduction and practice of Flutter, providing systematic learning articles about Flutter. See the corresponding source code here: The source code of Flutter Introduction and Practical column. If you have any questions, please add me to the wechat account: island-coder.
👍🏻 : feel the harvest please point a praise to encourage!
🌟 : Collect articles, easy to look back!
💬 : Comment exchange, mutual progress!