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 errorWidgetBuild 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!