Flutter 多个obs状态绑定同一个Widget异步刷新的解决方法

Flutter 多个obs状态绑定同一个Widget异步刷新的解决方法

今天修改flutter的老项目时发现,如果同一个组件使用两个不同的obs来刷新状态时,在某些情况下会出现体验不好的效果。

例子

举一个简单的例子好了

代码

比如说我要控制 TextField的两个状态,一个obs控制上面的文字,另一个obs控制TextField加载完成后是否自动聚焦。

所以我会定义两个 obs 变量

final title = "默认".obs;
final autofocus = false.obs;	// 默认为不自动聚焦

调用组件位置:

Obx(() => 
    // TextField 无法直接设置 title 值,这里做一个封装
    CustomTextField(
    	text : text.value,
        autofocus : autofocus.value,
        onSubmit : (text) {
            // 这里是 TextField 提交回调
            // 此时要不自动唤起键盘
            autofocus.value = false;
            // TextField 提交时会修改 title 的值从而令这里的 text 刷新变化
            title.value = text;
        }
    )
);

这时只要titleautofocus中其中一个改变都会引起CustomTextField的刷新。

现在有一个接口:

void setAutofocus(bool isAutofocus) {
    autofocus.value = isAutofocus;
}

预期效果

调用 setAutofocus 设置为 true 刷新CustomTextField会自动唤起键盘,然后输入修改,修改完成后,刷新修改后的值,并且回到只读状态。

问题

好像没什么问题对吧,我们细看一下这个回调

autofocus.value = false;后异步刷新,然后不调用键盘。

title.value = text;后异步刷新这个控件,然后正确显示文字。

autofocus刷新控件时,由于title还没更新,导致在获取文字时得到了旧值,此时显示的文字会瞬间回退到上一版本,然后等待title刷新控件时,才会显示正确的结果。虽然仅仅只是一瞬间,但很明显,达不到预期效果。

然后试着调换两行代码,

此时虽然文字不再闪现了,但由于title刷新控件时,autofocus是旧值,即true导致键盘闪现升起然后降下,又寄了。

解决方法

其实主要的问题就是,在刷新时无法获取到新值。

那么我们就可以创建一个不会导致控件刷新的正常变量来一起控制控件的状态,如:

bool editing = false;	// 默认不在编写状态

控件的autofocus设置成autofocus.value && editing

然后我们在setAutofocustrue的时候,将editing也设置为true

这时刷新控件,autofocus 属性为true

修改完成后,先将editing修改为false,不会导致控件刷新。

先提交结果,文字修改,由于autofocus属性此时判断为false就不会导致键盘被唤醒。

然后再调用autofocus.value = false;会自动刷新状态,但由于editing已经为false ,所以状态其实没有变动。

如果遇到更新文字比较慢的时候(如需要更新数据库),可以使用定时器将autofocus.value = false;延后一点运行。

总结

解决方法其实就是用一个变量来缓存此时的结果,提供给第一次刷新变量的控件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值