用最简单的方式说清楚flutter中get框架里update()方法为什么能刷新UI?

744 阅读2分钟

为什么在GetxController里调用upate()方法就能更新UI?答案其实就一句话:因为GetBuilder其实是一个StatefulWidget,而update()其实就是变相的调用了setState((){})

太长不看版请看前言。

在使用Get的时候我喜欢用GetBuilder而不是Obx(之前也没仔细研究原理啥的,反正作者说的是GetBuilder性能更好),但是其实使用Obx我认为应该也差不了多少,个人选择而已。

我一般是这么写页面的↓

UI页面:

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

import 'test_logic.dart';

class TestPage extends StatelessWidget {
  TestPage({super.key});

  final TestLogic logic = Get.put(TestLogic());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Hello get'),
      ),
      body: GetBuilder<TestLogic>(builder: (logic) {
        return Text('count is: ${logic.count}');
      }),
      floatingActionButton: FloatingActionButton(
        onPressed: logic.add,
        child: const Icon(Icons.add),
      ),
    );
  }
}

GetxController页面:

import 'package:get/get.dart';

class TestLogic extends GetxController {
  int count = 0;

  void add() {
    count++;
    update();
  }
}
simulator_screenshot_FFF66D13-2161-45B3-A1E2-6846925717CF.png

点击加号就能刷新UI了!但是,为什么可以刷新页面呢?

正文开始(由于只探究最简单的原理,很多无关的代码已省略)

GetBuilder其实是一个StatefulWidget的封装类而已,本质还是一个StatefulWidget

上源码:

// 这里就是给一个返回Widget的方法取了一个别名而已
typedef GetControllerBuilder<T extends DisposableInterface> = Widget Function(
    T controller);
    
class GetBuilder<T extends GetxController> extends StatefulWidget {
  final GetControllerBuilder<T> builder;
  
  @override
  GetBuilderState<T> createState() => GetBuilderState<T>();
}

class GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> {

  T? controller;

  @override
  void initState() {
    controller = GetInstance().find<T>(tag: widget.tag);
    // 这个addListener在GetxController定义的,下面有写
    controller?.addListener((){
        if (mounted) setState(() {});
    })
  }

  @override
  Widget build(BuildContext context) {
    return widget.builder(controller!);
  }
}

上面就是GetBuilder的核心代码,剔除了各种检查与其他idtag等等的功能。从里面我们可以看出在initState里给controller添加了一个更新UI的方法setState(() {}),所以在controller里就可以更新UI了。

本文到此结束,但是还有对知识渴望的(不死心的)同学还是继续来看看GetxController吧:

typedef GetStateUpdate = void Function();

abstract class GetxController {
    List<GetStateUpdate?>? _updaters = <GetStateUpdate?>[];

    void update([List<Object>? ids, bool condition = true]) {
        refresh();
    }
    
    void refresh() {
        _notifyUpdate();
    }
    
    void _notifyUpdate() {
      for (var element in _updaters!) {
        element!();
      }
    }
    
    // 这里在GetBuilderState里添加的方法
    Disposer addListener(GetStateUpdate listener) {
      _updaters!.add(listener);
      return ...;
    }

}

get已学会,下一个~