0

我想使用maps_launcher包启动谷歌地图。

当我将下面的 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)
4

2 回答 2

0

我认为它launchQuery返回 a bool,这在编译器看来,就像你试图给一个bool想要 a 的参数void Function?

我认为这会解决它。

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

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

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

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

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

于 2021-12-31T22:28:25.013 回答
0

好吧,我很高兴但很失望地报告这是一个初学者的错误产生了这个错误。

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

这是一个字符串:

child: businesses[index].address

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

child: Text(businesses[index].address)

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

于 2022-01-01T02:00:13.180 回答