【问题标题】:Why does my Flutter TextButton onPressed function generate a type assignment mismatch?为什么我的 Flutter TextButton onPressed 函数会生成类型分配不匹配?
【发布时间】:2021-12-31 21:04:53
【问题描述】:

我想使用 maps_launcher 包启动 Google 地图。

当我将下面的 TextButton 代码复制到 MaterialApp 主页部分的新项目中(或剥离我自己的 main.dart)时,它可以正常工作。 (编辑:它必须包装在容器或脚手架中才能工作,否则我会收到相同的类型不匹配错误。)

但是,由于某种我不知道的原因,我在所需的结构中不断遇到两个错误之一:

场景/错误 A

当我使用这段代码时:

onPressed: MapsLauncher.launchQuery(businesses[index].address)

我收到此错误:

The argument type 'Future<bool>' can't be assigned to the parameter type 'void Function()?'.

场景/错误 B

当我使用这段代码时:

我收到此错误:

════════ Exception caught by widgets library ═══════════════════════════════════
The following _TypeError was thrown building:
type 'String' is not a subtype of type 'Widget'

When the exception was thrown, this was the stack
#0      BusinessList.build.<anonymous closure>.<anonymous closure>
#1      SliverChildBuilderDelegate.build
#2      SliverMultiBoxAdaptorElement._build
#3      SliverMultiBoxAdaptorElement.createChild.<anonymous closure>
#4      BuildOwner.buildScope
#5      SliverMultiBoxAdaptorElement.createChild
#6      RenderSliverMultiBoxAdaptor._createOrObtainChild.<anonymous closure>
#7      RenderObject.invokeLayoutCallback.<anonymous closure>
#8      PipelineOwner._enableMutationsToDirtySubtrees
#9      RenderObject.invokeLayoutCallback
#10     RenderSliverMultiBoxAdaptor._createOrObtainChild
#11     RenderSliverMultiBoxAdaptor.addInitialChild
#12     RenderSliverList.performLayout
#13     RenderObject.layout
#14     RenderSliverEdgeInsetsPadding.performLayout
#15     RenderSliverPadding.performLayout
#16     RenderObject.layout
#17     RenderViewportBase.layoutChildSequence
#18     RenderViewport._attemptLayout
#19     RenderViewport.performLayout
#20     RenderObject.layout
#21     RenderProxyBoxMixin.performLayout
#22     RenderObject.layout
#23     RenderProxyBoxMixin.performLayout
#24     RenderObject.layout
#25     RenderProxyBoxMixin.performLayout
#26     RenderObject.layout
#27     RenderProxyBoxMixin.performLayout
#28     RenderObject.layout
#29     RenderProxyBoxMixin.performLayout
#30     RenderObject.layout
#31     RenderProxyBoxMixin.performLayout
#32     RenderObject.layout
#33     RenderProxyBoxMixin.performLayout
#34     RenderObject.layout
#35     RenderProxyBoxMixin.performLayout
#36     RenderCustomPaint.performLayout
#37     RenderObject.layout
#38     RenderProxyBoxMixin.performLayout
#39     RenderObject.layout
#40     MultiChildLayoutDelegate.layoutChild
#41     _ScaffoldLayout.performLayout
#42     MultiChildLayoutDelegate._callPerformLayout
#43     RenderCustomMultiChildLayoutBox.performLayout
#44     RenderObject._layoutWithoutResize
#45     PipelineOwner.flushLayout
#46     RendererBinding.drawFrame
#47     WidgetsBinding.drawFrame
#48     RendererBinding._handlePersistentFrameCallback
#49     SchedulerBinding._invokeFrameCallback
#50     SchedulerBinding.handleDrawFrame
#51     SchedulerBinding._handleDrawFrame
#55     _invoke (dart:ui/hooks.dart:150:10)
#56     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:270:5)
#57     _drawFrame (dart:ui/hooks.dart:114:31)
(elided 3 frames from dart:async)

完整代码

这是产生上述错误的代码(在粘贴过程中删除了包导入):

class BusinessList extends StatelessWidget {
  const BusinessList({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Business List')),
      body: StreamBuilder(
        stream: FirebaseFirestore.instance
            .collection('businesses')
            .snapshots()
            .map((snapshot) => snapshot.docs
                .map((doc) => Business.fromJson(doc.data()))
                .toList()),
        builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const CircularProgressIndicator();
          }
          if (snapshot.hasData) {
            if (snapshot.data!.isNotEmpty) {
              final businesses = snapshot.data;
              return ListView.builder(
                itemCount: businesses!.length,
                itemBuilder: (BuildContext context, int index) {
                  return Card(
                    child: Column(
                      children: [
                        ExpansionTile(
                          leading: const Icon(Icons.business),
                          title: Text(businesses[index].name),
                          subtitle: Text(businesses[index].category),
                          children: [
                            ListTile(
                              leading: const Icon(Icons.location_pin),
                              title: TextButton(
                                child: businesses[index].address,
                                onPressed: () => MapsLauncher.launchQuery(
                                    businesses[index].address),
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                  );
                },
              );
            }
          }
          return const Text('error');
        },
      ),
    );
  }
}

我的代码(第 42 行)的红色下划线部分是:

MapsLauncher.launchQuery(businesses[index].address)

【问题讨论】:

  • 由于未来的方法,请尝试使用onPressed()async{ await MapsLauncher...}。如果需要,请等待
  • @YeasinSheikh 感谢您分享这个想法!可悲的是,无论是否使用 async/await,它都会返回相同的错误(场景 B)。 (试过:onPressed: () async =>await MapsLauncher...)

标签: flutter flutter-onpressed url-launcher


【解决方案1】:

我认为是launchQuery 返回一个bool,这在编译器看来,就像您试图将bool 提供给需要void Function? 的参数一样

我认为这会解决它。

onPressed: () => MapsLauncher.launchQuery(businesses[index].address),

或者您可能需要执行此操作,具体取决于 launchQuery 的工作方式:

onPressed: () async => await MapsLauncher.launchQuery(businesses[index].address),

这解决了类型不匹配的问题,因为添加 () =&gt; 会告诉编译器您正在给它一个函数,以便在按下按钮时执行 onPressed

免责声明:这是未经测试的代码

【讨论】:

  • 感谢您分享这个想法,但我之前曾尝试过,但没有取得积极成果。为了完整起见,我在原始帖子中添加了它。
【解决方案2】:

好吧,我很高兴但很失望地报告说这是一个初学者的错误导致该错误。

问题实际上不在于 onPressed,而在于需要包装字符串的 Widget 的孩子。

这是一个字符串:

child: businesses[index].address

所以我所要做的就是把它包装成这样:

child: Text(businesses[index].address)

当错误似乎在其他地方而不是实际位置时,这真是令人沮丧。我希望有一天这对某人有所帮助...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-13
    • 2017-01-04
    • 1970-01-01
    • 2019-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-29
    相关资源
    最近更新 更多