You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter泛型数据表:如何传递类类型给'is'运算符检查状态

解决泛型Bloc数据表滚动加载的类型判断问题

问题根源

你遇到的错误是因为Dart的is运算符要求右侧必须是类型,但你现在传递的widget.stateDataDisplayed是BlocState的实例对象,不是类型,所以编译器无法识别。

正确实现方式

要实现泛型版本,需要把GenericDataTable定义为泛型类,通过泛型参数约束状态和事件的类型,而不是传递实例。

修改后的完整代码

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:track/src/abstract_classes/bloc.dart';

// 定义泛型类,约束StateType为BlocState子类,EventType为BlocEvent子类
class GenericDataTable<StateType extends BlocState, EventType extends BlocEvent> extends StatefulWidget {
  late double screenWidth, screenHeight;
  final List<String> columnsTitles;
  // 明确blocController的类型,同时要求它有hasNext属性(假设你的Bloc基类已定义该属性)
  final Bloc<BlocEvent, StateType> blocController;
  final EventType eventLoadMoreData;

  GenericDataTable({
    Key? key,
    required this.blocController,
    required this.eventLoadMoreData,
    required this.columnsTitles,
    required this.screenWidth,
    required this.screenHeight,
  }) : super(key: key);

  @override
  State<GenericDataTable<StateType, EventType>> createState() => _GenericDataTableState<StateType, EventType>();
}

class _GenericDataTableState<StateType extends BlocState, EventType extends BlocEvent> extends State<GenericDataTable<StateType, EventType>> {
  final ScrollController scrollController = ScrollController();

  @override
  void initState() {
    scrollController.addListener(scrollListener);
    super.initState();
  }

  @override
  void dispose() {
    scrollController.dispose();
    super.dispose();
  }

  void scrollListener() {
    if (scrollController.offset >= scrollController.position.maxScrollExtent &&
        !scrollController.position.outOfRange) {
      // 直接用泛型StateType做类型判断,同时检查hasNext
      if (widget.blocController.state is StateType && widget.blocController.hasNext) {
        widget.blocController.add(widget.eventLoadMoreData);
      }
    }
  }

  // 补充数据表构建逻辑示例
  @override
  Widget build(BuildContext context) {
    return DataTable(
      columns: widget.columnsTitles.map((title) => DataColumn(label: Text(title))).toList(),
      rows: [], // 替换为你的实际数据行渲染逻辑
    );
  }
}

使用示例

调用泛型组件时,直接指定具体的状态和事件类型:

GenericDataTable<StateClientListDisplayed, EventDisplayClients>(
  blocController: _blocController,
  eventLoadMoreData: EventDisplayClients(),
  columnsTitles: ['姓名', '邮箱'],
  screenWidth: MediaQuery.of(context).size.width,
  screenHeight: MediaQuery.of(context).size.height,
)

关键说明

  • 泛型参数StateType和EventType分别约束了需要判断的状态类型和触发的事件类型,避免了传递实例的错误
  • 明确blocController的类型为Bloc<BlocEvent, StateType>,确保编译器能识别state的类型和hasNext属性
  • 移除了原本的stateDataDisplayed参数,因为泛型类型已经足够做is判断

内容的提问来源于stack exchange,提问作者rambo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 14:25:28