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 {
  
  _ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
  
  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) {}
     
     
      
  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);

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

abstract class StatefulWidget extends Widget {
  const StatefulWidget({ super.key });
  
  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
  1. 可以根据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代码

代码

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: pyinstaller-hooks-contrib是一个用于PyInstaller的插件集合,它提供了一些额外的钩子和工具,可以帮助PyInstaller打包Python应用程序时更好地处理第三方库和依赖项。这个插件集合可以让开发者更轻松地打包和分发他们的Python应用程序。 ### 回答2: pyinstaller-hooks-contrib是一个库,它包含了许多用于PyInstaller的钩子,用于识别和处理不同的Python包和模块。 在PyInstaller中,钩子是指特定的脚本,它可以识别和处理Python程序中额外的依赖关系,以便正确地构建可执行文件。通常情况下,PyInstaller的核心程序只能处理Python的标准库和一些常见的第三方库,但是许多Python程序通常使用许多其他库和模块,这些库和模块需要通过钩子来处理。 pyinstaller-hooks-contrib库中的钩子可以帮助PyInstaller自动处理各种不同类型的Python模块和包。这些钩子的作用包括: 1.添加Python模块到可执行文件 2.处理特定的Python模块依赖库 3.处理模块内的资源文件 4.添加额外的数据文件到可执行文件 5.处理特定Python模块的数据文件 钩子的使用很简单,只需要将钩子文件放置在Helper Scripts目录下即可,PyInstaller将自动识别并在其构建过程中使用这些钩子。但是,需要注意的是,当钩子的更新或版本升级时,需要手动更新PyInstaller,并且可能需要更新钩子文件以适应更改。 总之,pyinstaller-hooks-contrib是一个非常有用的库,它使得PyInstaller可以轻松地处理各种不同类型的Python模块和包,以便将其转换为可执行文件。 ### 回答3: pyinstaller-hooks-contrib 是 PyInstaller 的一个插件,它可以帮助开发者在使用 PyInstaller 打包 Python 项目时,更高效地处理项目中的非 Python 文件。 在项目中,除了 .py 文件以外,我们还经常需要使用其它类型的文件,如图标、资源文件、配置文件等。这些文件的处理可能会影响到项目在不同平台上的可移植性和运行情况。 pyinstaller-hooks-contrib 可以让开发者方便地将这些文件打包进可执行文件中,并保持它们的相对路径关系。此外,该插件还提供了一些常用的钩子(hook)和文件类型处理器,使得开发者无需再手动指定这些需要打包的文件和其所需的依赖库。 例如,该插件提供了 win-icon 补丁,使得在 Windows 平台上为可执行文件添加图标更为简便。同时,该插件还支持打包 PyQt5 和 PySide2 等 GUI 库所需要的资源文件,避免了因打包不当而导致软件界面出现异常的问题。 总之,pyinstaller-hooks-contrib 为 Python 开发者提供了一系列方便实用的工具,能够让开发者更高效地进行跨平台软件开发和打包。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值