ClojureDart:如何实现组件间状态通信并确保子组件同步更新?
解决ClojureDart中父组件状态更新后子CustomPainter不刷新的问题
这个问题的核心是你没用到ClojureDart的响应式状态管理机制!普通变量的变化不会被框架感知,自然没法触发组件重渲染,下面一步步给你解决:
步骤1:把普通变量改成响应式状态
在父组件的Scaffold里,别用普通let变量存transforms,改用use-state钩子。这个钩子会返回状态值和专属的更新函数,只有通过这个更新函数修改状态,框架才会知道数据变了,进而触发组件重渲染。
示例代码:
(defn parent-scaffold [] (let [[transforms set-transforms] (use-state [])] ;; 初始化空的Offset集合 (scaffold :app-bar (app-bar :title (text "Custom Painter Demo")) :body (my-custom-painter transforms) ;; 把响应式状态传给子组件 :floating-action-button (floating-action-button :on-pressed (fn [] ;; 必须用set-transforms更新状态,不能直接conj普通变量 (set-transforms (conj transforms (Offset. (rand 300) (rand 500))))) :child (icon Icons/add)))))
步骤2:让CustomPainter正确响应数据变化
你的子组件CustomPainter需要实现should-repaint方法,明确告诉Flutter:当传入的transforms变了,就得重新绘制。同时要把transforms绑定到CustomPainter的delegate属性上,方便在should-repaint里对比新旧数据。
示例代码:
(defn my-custom-painter [transforms] (custom-painter :painter (reify CustomPainter (paint [this canvas size] ;; 遍历transforms绘制每个点 (doseq [offset transforms] (-> canvas (draw-circle offset 6.0 (paint :color Colors/blue :style PaintingStyle/fill))))) (should-repaint [this old-delegate] ;; 对比新旧transforms,不一样就返回true触发重绘 (not= transforms (.transforms old-delegate)))) ;; 把transforms绑定到delegate属性,方便旧delegate访问 :transforms transforms))
核心逻辑说明
ClojureDart基于Flutter的状态管理规则,只有响应式状态(通过use-state、use-reducer这类钩子创建的状态)发生变化时,组件才会自动重渲染。普通变量的修改完全不会被框架察觉,所以子组件拿不到更新后的数据。
另外CustomPainter默认不会自动重绘,必须通过should-repaint明确指定重绘条件——当传入的transforms和旧数据不一致时,就返回true让Flutter重新绘制画布。
内容的提问来源于stack exchange,提问作者Adina
相关产品推荐
相关产品推荐

