hooks-riverpod 使用

简介: hooks-riverpod 使用
1. hook

需要继承HookWidget

useMemoized

useRef useCallback 通过内部使用useMemoized 只调用一次

useEffect

1.1 属性 行为 组合成了状态,除了状态还有作用
1.2 keys

指定是否应重用 [HookState] 或应创建新的对象列表。创建新的 [Hook] 时,框架会使用

[Hook.shouldPreserveState] 检查键是否匹配。如果没有,之前创建的 [HookState] 将被释放,并使用 [Hook.createState] 创建一个新的,然后是 [HookState.initHook]

2. useMemoized

缓存复杂对象的实例。

useMemoized->_MemoizedHook->_MemoizedHookState-> late final T value = hook.valueBuilder()

build 返回的一直都是value, 需要手动调用

一般useFuture useMemoized 配合使用

3. useCallback

缓存函数对象的实例

4. useRef

创建一个包含单个可变属性的对象。改变对象的属性是无效的。这对于在“构建”调用之间共享状态非常有用,而不会导致不必要的重构。

5. useEffect

对于需要取消的

useEffect->_EffectHook->_EffectHookState->initHook()->disposer = hook.effect()->dispose() => disposer?.call()

会在第一次build的时候主动调用,无需手动调用

dispose

6.1 其他钩子

useValueNotifier

useListenable->_ListenableHook->_ListenableStateHook->_listener->setState

useValueListenable->_UseValueListenableHook->_ListenableHook->

useValueListenable比useListenable多加了一个方法,有了返回值

useListenable相当于ValueListenableBuilder->_valueChanged->setState

useListenableSelector 多了一个条件,如果两个值不一样的时候才build

useAnimationController

useAnimation 相当于AnimatedBuilder->_handleChange->setState


useStreamController

useStream 相当于StreamBuilder


useFuture 相当于FutureBuilder


useReducer state一个是对象, action一个是参数

通过dispatch发送参数来返回新的state

6.2 useXXXX 自定义钩子
7. riverpod

runApp(const ProviderScope(child: App()));

需要继承ConsumerWidget 使用WidgetRef ref

继承 StateNotifier ChangeNotifier

ChangeNotifierProvider StateNotifierProvider

ref.watch 观察刷新

ref.read 修改

ref.listen 监听

8. 常用Provider

FutureProvider

StreamProvider.family可以传入参数

FutureProvider.autoDispose

StateNotifierProvider

StateController

Provider

9. 局部刷新

ValueListenableBuilder

ValueNotifier

Listenable

10. Consumer使用 ,局部刷新

提供程序更新时重建尽可能少的小部件

class Example extends StatefulWidget {
  @override
  _ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
  @override
  Widget build(BuildContext context) {
    return Consumer(
      builder: (context, ref, child) {
        final value = ref.watch(helloWorldProvider);
        return Text(value); // Hello world
      },
    );
  }
}
11. HookBuilder使用 ,局部刷新
      HookBuilder(builder: (BuildContext context){
                      final num = useState(8);
                      print("HookBuilder-build");
                       return TextButton(
                           onPressed: () {
                             num.value++;
                           },
                           child: Text("num=${num.value}"));
                    })

12 . hook源码分析
Hook
  1. HookWidget vs StatefulWidget
  2. HookElement vs StatefulElement
  3. HookState vs State
abstract class Hook<R> with Diagnosticable {
    final List<Object?>? keys;
    static R use<R>(Hook<R> hook) {
     return HookElement._currentHookElement!._use(hook);
    }
    
     static bool shouldPreserveState(Hook<Object?> hook1, Hook<Object?> hook2) {}
     
     
      @protected
  HookState<R, Hook<R>> createState();
}
1. HookWidget vs StatefulWidget
abstract class HookWidget extends StatelessWidget {
  /// Initializes [key] for subclasses.
  const HookWidget({Key? key}) : super(key: key);

  @override
  _StatelessHookElement createElement() => _StatelessHookElement(this);
}

abstract class StatefulWidget extends Widget {
  const StatefulWidget({ super.key });
  @override
  StatefulElement createElement() => StatefulElement(this);
  
  State createState();
}

2. StatefulElement vs HookElement
///
class StatefulElement extends ComponentElement {
    StatefulElement():_state = createState(){
        _state.element = this;
        _state.widget = widget;
    }
        
     _firstBuild(){
        _state.initState();
        _state.didChangeDependencies();
        rebuild();///performRebuild();
    }
    
     _update(){
        _state.didUpdateWidget();
        rebuild();
    }
    
    build()=>_state.build(this);
    
    performRebuild(){
      state.didChangeDependencies();
    }
    
    activate(){
    _state.activate();
    }
    
    deactivete(){
    _state.deactivate():
    }
    
    unamount(){
     _state.dispose();
    }
}


class _StatelessHookElement extends StatelessElement with HookElement {
  _StatelessHookElement(HookWidget hooks) : super(hooks);
}


HookElement
  1. 一个hookElement中有多个Hook,每个hook对应一个hookstate
  2. 可以根据keys,hookstate不变,但是hook重新赋值 和State对weidget(key,runtype)是一样的
mixin HookElement on ComponentElement {

static HookElement? _currentHookElement;
  _Entry<HookState<Object?, Hook<Object?>>>? _currentHookState;
  
  ///一个HookElement对应多个HookState
  final _hooks = LinkedList<_Entry<HookState<Object?, Hook<Object?>>>>();
  final _shouldRebuildQueue = LinkedList<_Entry<bool Function()>>();
  LinkedList<_Entry<HookState<Object?, Hook<Object?>>>>? _needDispose;
  bool? _isOptionalRebuild = false;
  Widget? _buildCache;



  Widget build() {
  final mustRebuild = _isOptionalRebuild != true ||
        _shouldRebuildQueue.any((cb) => cb.value());

    _isOptionalRebuild = null;
    _shouldRebuildQueue.clear();

    if (!mustRebuild) {
      return _buildCache!;
    }
    _currentHookState = _hooks.isEmpty ? null : _hooks.first;
    HookElement._currentHookElement = this;
   return _buildCache;
  }

 R _use<R>(Hook<R> hook) {
 ///如果为空应为列表中为空 直接添加
   if (_currentHookState == null) {
      _appendHook(hook);
    }else if(hook.runtimeType != _currentHookState!.value.hook.runtimeType){
     /// 是一个新的hook
      _appendHook(hook);
    }else if (hook != _currentHookState!.value.hook) {
        
         final previousHook = _currentHookState!.value.hook;
      if (Hook.shouldPreserveState(previousHook, hook)) {
         ///说明keys不一样了 需要重新hook
        _currentHookState!.value
          .._hook = hook
          ..didUpdateHook(previousHook);
      } else {
      ///新创建一个State
        _needDispose ??= LinkedList();
        _needDispose!.add(_Entry(_currentHookState!.value));
        _currentHookState!.value = _createHookState<R>(hook);
      }
    
    }
     final result = _currentHookState!.value.build(this) as R;
       _currentHookState = _currentHookState!.next;
    return result;
  }
 }

3. HookState vs State
///State
bool get mounted => _element != null;



///HookState
 void markMayNeedRebuild() {
    if (_element!._isOptionalRebuild != false) {
      _element!
        .._isOptionalRebuild = true
        .._shouldRebuildQueue.add(_Entry(shouldRebuild))
        ..markNeedsBuild();
    }
    assert(_element!.dirty, 'Bad state');
  }


13. studyflutter代码

代码

相关文章
|
容器
flutter GestureDetector 的 behavior属性
【8月更文挑战第21天】
503 4
|
5月前
|
存储 人工智能 前端开发
PinMe:零成本三秒发布你的网站
PinMe是一款零配置、去中心化的前端部署工具,基于IPFS实现静态网站一键发布。无需服务器、域名或复杂配置,支持网页拖拽或命令行上传,自动生成可验证、抗篡改的永久链接。单文件200MB、整站1GB以内免费部署,让发布变得简单、安全、可靠。🚀
1292 11
PinMe:零成本三秒发布你的网站
|
Linux iOS开发 MacOS
Flutter桌面开发之窗口管理
今天跟着大家一起学习桌面开发之窗口管理,关于桌面窗口管理,我网上查了很久资料,我觉得window_manager 这个插件几乎可以满足市面上大部分需求了
Flutter桌面开发之窗口管理
Flutter 121: 图解简易 Slider 滑动条
0 基础学习 Flutter,第一百二十一步:简单学习 Slider 滑动条!
1968 0
Flutter 121: 图解简易 Slider 滑动条
|
机器学习/深度学习 人工智能 供应链
2024年的供应链回顾与2025展望:数字化转型与韧性提升
2024年的供应链回顾与2025展望:数字化转型与韧性提升
|
人工智能 算法 计算机视觉
【01】opencv项目实践第一步opencv是什么-opencv项目实践-opencv完整入门以及项目实践介绍-opencv以土壤和水滴分离的项目实践-人工智能AI项目优雅草卓伊凡
【01】opencv项目实践第一步opencv是什么-opencv项目实践-opencv完整入门以及项目实践介绍-opencv以土壤和水滴分离的项目实践-人工智能AI项目优雅草卓伊凡
577 63
【01】opencv项目实践第一步opencv是什么-opencv项目实践-opencv完整入门以及项目实践介绍-opencv以土壤和水滴分离的项目实践-人工智能AI项目优雅草卓伊凡
|
人工智能 自然语言处理 API
云栖发布:通义听悟AI能力再进化,开放API接口
云栖发布:通义听悟AI能力再进化,开放API接口
|
存储 UED 开发者
Flutter鸿蒙版本灵活使用方法间的回调处理复杂化的逻辑
在 Flutter 开发中,灵活使用函数回调可以提高代码的可重用性、简化异步编程、增强解耦设计和提升用户体验。本文通过一个简单的示例,展示了如何在 Flutter 中实现函数调用和回调的基本使用。示例代码包括主入口、页面组件和回调函数的定义与调用,详细解析了每个部分的功能和作用。通过这种方式,开发者可以在操作完成后执行特定逻辑,使代码更易读和维护。
362 0
|
移动开发 监控 网络协议
基于Socket通讯(C#)和WebSocket协议(net)编写的两种聊天功能(文末附源码下载地址)
基于Socket通讯(C#)和WebSocket协议(net)编写的两种聊天功能(文末附源码下载地址)
|
移动开发 缓存 Dart
Pad大屏&Flutter多引擎适配之路
# 背景 在电商场景中iPad的大屏拥有比普通手机相比更大的屏幕,对于购物体验而言,如能充分利用好iPad的大屏体验,无疑提高用户购买体验,但一直以来在混合栈应用特别是Flutter混合栈中,在iPad大屏适配和Flutter多引擎适配都是个老大难问题。本文会介绍闲鱼在这iPad适配中的各个疑难点。 # 分屏模式 华为,oppo等厂商折叠屏的方案。界面会在展开和折叠时展示不同的视图样式。op
1322 0
Pad大屏&Flutter多引擎适配之路