Flutter 中 ValueNotifier<List<T>> 监听问题解决

1. 起因

开发中遇到一个问题 ValueNotifier<List<T>> 监听失败, 初步确认原因是数组值发生改变但是地址未发生改变,与 iOS 监听数组需要特别处理一样;需要二次赋值触发地址改变,触发监听机制;

2.结果:完美解决问题

最终简单封装如下:

/// 泛型数组监听
class ValueNotifierList<T> extends ValueNotifier<List<T>> {

  ValueNotifierList(List<T> initValue) : super(initValue);

  void add(T item) {
    value.add(item);
    _copyValue();
  }

  /// 删除
  void remove(int index) {
    if (value.length < index) {
      return;
    }
    value.removeAt(index);
    _copyValue();
  }

  /// 删除最后
  void removeLast() {
    if (value.length == 0) {
      return;
    }
    value.removeLast();
    _copyValue();
  }

  void removeAll() {
    value.clear();
    _copyValue();
  }
  /// 利用深copy 重新赋值,触发监听
  void _copyValue() {
    value = [...value];
  }

  @override
  String toString() {
    return "${this.runtimeType} 共 ${value.length} 件商品}";
  }
}

3. example:

/// ValueNotifier
static ValueNotifierList valueNotifierList = ValueNotifierList(<OrderModel>[]);
/// ValueNotifier(addListener无效 因为数组地址未发生改变, 推荐使用 ValueNotifierList)
static ValueNotifier<List<OrderModel>> valueNotifierListOrigin = ValueNotifier(<OrderModel>[]);

...

@override
void initState() {
  super.initState();
  
  valueNotifierList.addListener(update);
  valueNotifierListOrigin.addListener(update);
}

@override
void dispose() {
  valueNotifierList.removeListener(update);
  valueNotifierListOrigin.removeListener(update);
  
  super.dispose();
}

...

void update() {
  showSnackBar(SnackBar(content: Text("数据变化监听回调, 刷新重建界面",)), true);
  setState(() {});
}

...

void handleActionNum({required ValueNotifierModel e, required int value, required int idx}) {
  switch (e.name) {
    case "valueNotifierList":
      {
        final e = OrderModel(name: '商品', id: 99, pirce: 1.00);
        if (value > 0) {
          valueNotifierList.add(e);
        } else {
          valueNotifierList.removeLast();
        }

        ddlog(valueNotifierList.toString());
        // ddlog("${cartModelOneKey.totalPrice}");
      }
      break;

    case "valueNotifierListOrigin":
      {
        final e = OrderModel(name: '商品', id: 99, pirce: 1.00);
        if (value > 0) {
          valueNotifierListOrigin.value.add(e);
        } else {
          valueNotifierListOrigin.value.removeLast();
        }
        
        update();///监听无效,需要手动调整

        ddlog(valueNotifierListOrigin.value.length.toString());
        // ddlog("${cartModelOneKey.totalPrice}");
      }
      break;
    default:
      break;
  }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容