以子类作为参数并返回的 Dart 回调函数出现类型错误

问题描述 投票:0回答:1

我遇到了

TypeError
,消息如下:

Type '(Job) => ListTile' is not a subtype of type '(Model) => Widget'

在我的 Flutter 应用程序中尝试通过传递回调来构建小部件时。回调类型定义为:

final Widget Function(T) listItemBuilder;

在课堂上:

class ListPageBuilder<T extends Model> extends StatefulWidget

在调用代码中,我用以下方式实例化了

ListPageBuilder

ListPageBuilder(
  listItemBuilder: (Job item) {
    return ListTile(
      key: Key(item.pk!),
      title: Text(item.title),
      subtitle: Text(item.description),
    );
  },
);

其中

Job
继承自
Model
。我希望这能起作用,因为
Job
Model
的子类,而
ListTile
Widget

这是完整代码

ListPageBuilder
实施


class ListPageBuilder<T extends Model> extends StatefulWidget {
  final bool canView;
  final bool canAdd;
  final String modelVerboseName;
  final Repository repository;
  final void Function()? onItemTap;
  final Widget Function(T) listItemBuilder;

  const ListPageBuilder({
    super.key,
    required this.modelVerboseName,
    required this.canView,
    required this.canAdd,
    required this.repository,
    required this.listItemBuilder,
    this.onItemTap,
  });
  @override
  State<ListPageBuilder> createState() => _ListPageBuilderState();
}

class _ListPageBuilderState extends State<ListPageBuilder> {
  @override
  void initState() {
    super.initState();
    fetchItems();
  }

  var items = [];
  int? nextPage = 1;
  bool _isLoading = true;
  final _scrollController = ScrollController();
  final _searchController = TextEditingController();

  String? getSearchTerm() {
    return _searchController.text.length >= 3 ? _searchController.text : null;
  }

  Map<String, dynamic> getFilters() {
    var filters = <String, dynamic>{"page": nextPage};
    var searchTerm = getSearchTerm();
    if (searchTerm != null) {
      filters["search"] = searchTerm;
    }
    return filters;
  }

  void fetchItems() async {
    if (nextPage == null) return;
    try {
      var response = await widget.repository.list(getFilters());
      var items = response.results;
      nextPage = response.next != null ? getPage(response.next!) : null;

      _isLoading = false;
      setState(() {
        this.items.addAll(items);
      });
    } on HttpException catch (e) {
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    _scrollController.addListener(() {
      var nextPageTriggerLimit =
          0.75 * _scrollController.position.maxScrollExtent;

      if (_scrollController.position.pixels > nextPageTriggerLimit &&
          !_isLoading) {
        _isLoading = true;
        fetchItems();
      }
    });

    return Scaffold(
      bottomNavigationBar: const AppNavigationBar(),
      floatingActionButton: widget.canAdd
          ? FloatingActionButton(
              onPressed: () {
                Navigator.pushNamed(context, "/customers/create");
              },
              child: const Icon(Icons.add),
            )
          : null,
      body: SafeArea(
        child: Center(
          child: Padding(
            padding: const EdgeInsets.all(8),
            child: widget.canView
                ? Column(
                    children: [
                      TextFormField(
                        decoration: InputDecoration(
                          hintText: "Rechercher un ${widget.modelVerboseName}",
                          suffixIcon: const Icon(Icons.search),
                        ),
                        controller: _searchController,
                        onChanged: (value) {
                          if (value.isEmpty || value.length >= 3) {
                            setState(() {
                              items = [];
                              nextPage = 1;
                              fetchItems();
                            });
                          }
                        },
                      ),
                      (items.isEmpty && _isLoading)
                          ? const SizedBox(
                              width: 50,
                              height: 50,
                              child: CircularProgressIndicator(),
                            )
                          : Expanded(
                              child: ListView.separated(
                                controller: _scrollController,
                                itemCount: items.length,
                                itemBuilder: (context, index) {
                                  var item = items[index];
                                  return widget.listItemBuilder(item);
                                },
                                separatorBuilder: (context, index) =>
                                    const Divider(),
                              ),
                            )
                    ],
                  )
                : const Center(
                    child: Text(
                      "Vous n'avez pas la permission de consulter cette page",
                    ),
                  ),
          ),
        ),
      ),
    );
  }
}

调用代码是

class JobListPage extends StatelessWidget {
  const JobListPage({super.key});

  @override
  Widget build(BuildContext context) {
    return ListPageBuilder<Job>(
      canView: true,
      canAdd: true,
      repository: jobRepository,
      modelVerboseName: "job",
      listItemBuilder: (Job item) {
        return ListTile(
          key: Key(item.pk!),
          title: Text(item.title),
          subtitle: Text(item.description),
        );
      },
    );
  }
}

如何解决这个问题?

flutter dart callback
1个回答
0
投票

我可以通过写作让它发挥作用

class JobListPage extends StatelessWidget {
  const JobListPage({super.key});

  @override
  Widget build(BuildContext context) {
    return ListPageBuilder<Job>(
      canView: true,
      canAdd: true,
      repository: jobRepository,
      modelVerboseName: "job",
      listItemBuilder: (Model item) {
        Job job = item as Job;
        return ListTile(
          key: Key(job.pk!),
          title: Text(job.title),
          subtitle: Text(job.description),
        );
      },
    );
  }
}

它不干净,但它有效,我仍在寻找更好的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.