美文网首页
GetX-响应式状态管理(被动)

GetX-响应式状态管理(被动)

作者: 存在即是美 | 来源:发表于2022-03-25 13:39 被阅读0次

官网地址:https://pub.flutter-io.cn/packages/get

关于状态管理,目前主流有四个: GetX,BLoC、MobX、Provider。
BLoC 非常安全和高效,但是非常复杂,理解与运用不适合初学者。
MobX 比 BLoC 更容易,而且是响应式的,但是需要使用一个代码生成器,需要时间等待,对开发效率有影响。
BloC(全局管理,event,形式类似mvvm):

  1. widget 触发event 事件
  2. bloc 接收event 事件并作出逻辑处理
    3.并把逻辑处理结果给返回出来
  3. UI展示数据
    所以,目前市场最常见的是Provider和GetX。
    但是,目前在pub上来看,GetX可能更受青睐。


    get.png
provider.png

相对于provide ,我觉得GetX更有优势的地方在于:GetX 不需要上下文,突破了InheritedWidget的限制,我们可以在全局和模块间共享状态,而Provider 在遇到非父子组件的状态管理问题,需要借助别的手段(eventbus,全局,单例)。
针对context做个简单的对比:provide中路由需要对 context 的依赖。

///原始
Navigator.push(context, MaterialPageRoute<void>(
      builder: (BuildContext context) {
        return NextScreen();
      },
    ));
///provider封装后
Navigator.pushNamed(context, RouteName.nextName);
///返回
Navigator.pop(context);
///GetX
Get.to(NextScreen())
///返回
Get.back();
///打开新页面,并且用新页面替换旧页面(删除旧页面)
Get.off(NextScreen());
///打开新页面并删除之前的所有路由
Get.offAll(NextScreen());
///导航到新页面,在返回时接收返回数据
var data = await Get.to(NextScreen());
///带返回值返回前一个路由,配合上面使用
Get.back(result: 'success');

通过Snackbar的使用来感受下getx

安装

dependencies:
  get: 

引入

import 'package:get/get.dart';

Snackbar使用
导入依赖后,在应用程序顶层把GetMaterialApp 作为顶层,然后通过Get.snackbar() 来显示 snackbar

import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: "GetX",
      home: Scaffold(
        appBar: AppBar(
          title: Text("GetX Title"),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () {
                  Get.snackbar("Snackbar 标题", "欢迎使用Snackbar");
                },
                child: Text("显示 Snackbar"))
            ],
          ),
        ),
      ),
    );
  }
}

效果图


Simulator Screen Shot - iPhone 8 - 2022-03-24 at 11.33.11.png
将
Get.snackbar("Snackbar 标题", "欢迎使用Snackbar");
替换成下方代码
Scaffold.of(context).showSnackBar(
       SnackBar(
            content: Text('Have a snack!'),
        ),
);

运行下会报一个错误

///报错原因是 : 在Scaffold子组件里的build方法可以才可以调用Scaffold.of方法
Scaffold.of() called with a context that does not contain a Scaffold.

上门这个错误有很多解决办法,例如抽离出一个子控件,使用GlobalKey存储ScaffoldState ,但是无疑都会增加代码量。

谈一下被动状态管理

被动状体管理 :通俗的讲就是当你改变一个值,相关小控件随之变化。
现有项目中我通常是采用mvvm加provider的方式,现在看下getx的实现

class ObxCountExample extends StatelessWidget {

  ///声明Rx变量以及改变计数器的方法
 //StringX  RxString
 //IntX RxInt
 //MapX RxMap
 //列表X  RxList
 //NumX RxNum
 //DoubleX  RxDouble
  RxInt count = RxInt(0);
  void increment() {
    count++;
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          ///使用Obx监听值的改变
          Obx(() => Text(
            "count的值为: $count",
            style: TextStyle(color: Colors.red, fontSize: 30),
          )),
          SizedBox(height: 20,),
          ElevatedButton(
              onPressed: () {
                increment();
              },
              child: Text("点我加1"))
        ],
      ),
    );
  }
}
Simulator Screen Shot - iPhone 8 - 2022-03-24 at 11.57.51.png

如果是一个类里的值发生改变

class Programmer {
  // rx 变量
  var name = "mabo".obs;
  var age = 30.obs;
}

class ObxCustomClassExample extends StatelessWidget {

  var programmer = Programmer();
  
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Obx(() => Text(
            "我的名字是 ${programmer.name.value}",
            style: TextStyle(color: Colors.red, fontSize: 30),
          )),
          SizedBox(height: 20,),
          ElevatedButton(
              onPressed: () {
                programmer.name.value = programmer.name.value.toUpperCase();
              },
              child: Text("转换为大写"))
        ],
      ),
    );
  }
}

上述 .obs 和 Rx([]) ,基本等价,都是obs状态管理的创建属性的方式

UI和逻辑分离-GetxController

核心思想:


逻辑.png

定义一个继承GetxController的类: 逻辑- Controller 层
定义一个GetBuilder类:界面- *View 层
controlelr 里面调用update() 刷新UI
首先,定义控制器继承自GetxController(生命周期(onInit()),onReady()),onClose()))

import 'package:get/get.dart';

class Teacher {
  // rx 变量
  var name = "mabo".obs;
  var age = 30.obs;
}

class MyController extends GetxController {

  // 第一种
  // var teacher = Teacher();
  //
  // void convertToUpperCase() {
  //   teacher.name.value = teacher.name.value.toUpperCase();
  // }

  // 第二种
  // var teacher =  Teacher(name: "Jimi", age: 18).obs;
  // void convertToUpperCase() {
  //   teacher.update((val) {
  //     teacher.value.name = teacher.value.name.toString().toUpperCase();
  //   });
  // }

  // 第三种
  var teacher = Teacher();

  void convertToUpperCase() {
    teacher.name.value = teacher.name.value.toUpperCase();
    update();
  }
}

之后,实例化控制器并使用

import 'package:flutter/material.dart';
import 'package:flutter_getx_example/GetXControllerExample/MyController.dart';
import 'package:get/get.dart';

class GetXControllerExample extends StatelessWidget {

  // 第一种
 // MyController myController = Get.put(MyController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("GetX Obx---GetXController"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            // 第一种
            // Obx(() => Text(
            //   "我的名字是 ${myController.teacher.name}",
            //   style: TextStyle(color: Colors.red, fontSize: 30),
            // )),
            // 第二种
            // GetX<MyController>(
            //   init: MyController(),
            //   builder: (controller) {
            //     return Text(
            //       "我的名字是 ${controller.teacher.name}",
            //       style: TextStyle(color: Colors.green, fontSize: 30),
            //     );
            //   },
            // ),
            // 第三种
            GetBuilder<MyController>(
              init: myController,
              builder: (controller) {
                return Text(
                  "我的名字是 ${controller.teacher.name}",
                  style: TextStyle(color: Colors.green, fontSize: 30),
                );
              },
            ),
            SizedBox(height: 20,),
            ElevatedButton(
              onPressed: () {
                // 第一种
                myController.convertToUpperCase();

                // 第二种
                // Get.find<MyController>().convertToUpperCase();

              },
              child: Text("转换为大写"))
          ],
        ),
      ),
    );
  }
}

实现效果


Simulator Screen Shot - iPhone 8 - 2022-03-24 at 13.43.55.png

GetxController UniqueID

开发的过程中会碰到一种情况,就是多个地方引用了同一个属性,但我只想单独更新某一个地方,那么就可以用UniqueID来进行区分。
首先,定义控制器继承自GetxController,并且定义uniqueID

import 'package:get/get.dart';

class CountController extends GetxController {
  var count = 0;

  void increment() {
    count++;
    update(['jimi_count']);
  }
}

class GetXControllerUniqueIDExample extends StatelessWidget {

 CountController countController = Get.put(CountController());

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       title: Text("GetX Obx---GetXController"),
     ),
     body: Center(
       child: Column(
         mainAxisAlignment: MainAxisAlignment.center,
         crossAxisAlignment: CrossAxisAlignment.center,
         children: [
           GetBuilder<CountController>(
             builder: (controller) {
               return Text(
                 "计数器值为: ${controller.count}",
                 style: TextStyle(color: Colors.red, fontSize: 30),
               );
             },
           ),
           GetBuilder<CountController>(
             id: 'jimi_count',
             builder: (controller) {
               return Text(
                 "计数器值为: ${controller.count}",
                 style: TextStyle(color: Colors.green, fontSize: 30),
               );
             },
           ),
           SizedBox(height: 20,),
           ElevatedButton(
             onPressed: () => countController.increment(),
             child: Text("增加"))
         ],
       ),
     ),
   );
 }
}

红色的没有改变,绿色的改变了


截屏2022-03-24 下午1.56.20.png

GetxService

GetView

除了状态管理、路由管理、依赖管理之外,还有网络数据的管理,有待补充。

相关文章

  • GetX-响应式状态管理(被动)

    官网地址:https://pub.flutter-io.cn/packages/get[https://pub.f...

  • GetX 响应式状态管理简介

    前言 我们用了几章讲述了 GetX 的简单状态响应管理,本篇开始来讲解 GetX 的响应式状态管理。关于响应式状态...

  • mobx简介

    官方文档-传送 MobX是响应式编程,实现状态的存储和管理。使用MobX将应用变成响应式可归纳为三部曲: 定义状态...

  • mobx 入门

    mobx 响应式状态管理库 安装 基础概念 所谓的响应式,既是将原有数据结构,例如 数组,对象等转变为可观察对象,...

  • vuex

    vuex 状态管理 简介:Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 s...

  • 状态管理

    响应式的编程框架中都会有一个永恒的主题——“状态管理”,无论是在React/Vue(两者都是支持响应式编程的web...

  • vue3较vue2的特别之处 - ref/toRef/toRef

    ref: 为值类型数据添加响应式状态示例: reactive: 为对象添加响应式状态示例: toRef: 用于为源...

  • Flutter了解之入门篇9-2(状态管理库)

    1. MobX库 基于观察者模式和响应式模式的状态管理库,将响应式数据和UI进行绑定(绑定是完全自动的)。使开发者...

  • Vue.js之vuex(状态管理)

    vuex是一个状态管理工具,类似于redux. 安装vuex Vuex 的状态管理存储是响应式的:就是当你的组件使...

  • Angular Form (响应式Form) 学习笔记

    Angular 响应式表单使用显式的、不可变的方式,管理表单在特定的时间点上的状态。对表单状态的每一次变更都会返回...

网友评论

      本文标题:GetX-响应式状态管理(被动)

      本文链接:https://www.haomeiwen.com/subject/xotdjrtx.html