Flutter ListView 热重载时出现了 CastError。

4

我在我的Flutter应用程序中发现了一个非常奇怪的错误。我正在使用一个具有itemExtend值的ListView。当在应用程序内导航时,一切都正常 - 控制台中没有错误消息。但是,在进行热重载之后,例如通过编辑并保存放置ListView的文件上的代码,我会收到许多RenderRepaintBoundary错误。

这是我的ListView:

return ListView.builder(
  padding: EdgeInsets.only(top: 25, bottom: 20),
  shrinkWrap: true,
  itemExtent: 95, // Error only appears if I add itemExtent
  physics: ClampingScrollPhysics(),
  itemCount: entriesController.guestbookEntries.length,
  itemBuilder: (BuildContext context, int index) {

    return GestureDetector(
      onLongPress: () async {
        // Some stuff
      },
      child: Text("Test Widget")
    );
  },
);

在热重载后,控制台会显示以下错误信息(但应用程序按预期工作):

[Easy Localization] Build [Easy Localization] Init Localization Delegate [Easy Localization] Init provider

════════ Exception caught by rendering library ═════════════════════════════════ The following _CastError was thrown during performLayout(): Null check operator used on a null value

The relevant error-causing widget was ListView When the exception was thrown, this was the stack #0 RenderSliverFixedExtentBoxAdaptor.performLayout #1 RenderObject.layout #2 RenderSliverEdgeInsetsPadding.performLayout #3 RenderSliverPadding.performLayout #4 RenderObject.layout ... The following RenderObject was being processed when the exception was fired: RenderSliverFixedExtentList#b073b relayoutBoundary=up11 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE RenderObject: RenderSliverFixedExtentList#b073b relayoutBoundary=up11 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: paintOffset=Offset(0.0, 25.0) (can use size) constraints: SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.idle, scrollOffset: 0.0, remainingPaintExtent: Infinity, crossAxisExtent: 390.0, crossAxisDirection: AxisDirection.right, viewportMainAxisExtent: Infinity, remainingCacheExtent: Infinity, cacheOrigin: 0.0) geometry: SliverGeometry(scrollExtent: 760.0, paintExtent: 760.0, maxPaintExtent: 760.0, cacheExtent: 760.0) scrollExtent: 760.0 paintExtent: 760.0 maxPaintExtent: 760.0 cacheExtent: 760.0 currently live children: 0 to 7 child with index 0: RenderIndexedSemantics#56371 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: index=0; layoutOffset=0.0 constraints: BoxConstraints(w=390.0, h=95.0) semantic boundary size: Size(390.0, 95.0) index: 0 child: RenderRepaintBoundary#1056f NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) layer: OffsetLayer#9f74a engine layer: OffsetEngineLayer#9b21b offset: Offset(0.0, 25.0) size: Size(390.0, 95.0) metrics: 83.3% useful (1 bad vs 5 good) diagnosis: this is a useful repaint boundary and should be kept child: RenderSemanticsGestureHandler#c0c8b NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) gestures: long press child: RenderPointerListener#c4b22 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) behavior: deferToChild listeners: down child with index 1: RenderIndexedSemantics#c082a NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: index=1; layoutOffset=95.0 constraints: BoxConstraints(w=390.0, h=95.0) semantic boundary size: Size(390.0, 95.0) index: 1 child: RenderRepaintBoundary#f5bbf NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) layer: OffsetLayer#003b7 engine layer: OffsetEngineLayer#75c0b offset: Offset(0.0, 120.0) size: Size(390.0, 95.0) metrics: 83.3% useful (1 bad vs 5 good) diagnosis: this is a useful repaint boundary and should be kept child: RenderSemanticsGestureHandler#eee56 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) gestures: long press child: RenderPointerListener#82ca0 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) behavior: deferToChild listeners: down child with index 2: RenderIndexedSemantics#dc0db NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: index=2; layoutOffset=190.0 constraints: BoxConstraints(w=390.0, h=95.0) semantic boundary size: Size(390.0, 95.0) index: 2 child: RenderRepaintBoundary#394b9 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) layer: OffsetLayer#19e8a engine layer: OffsetEngineLayer#11d00 offset: Offset(0.0, 215.0) size: Size(390.0, 95.0) metrics: 83.3% useful (1 bad vs 5 good) diagnosis: this is a useful repaint boundary and should be kept child: RenderSemanticsGestureHandler#0a954 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) gestures: long press child: RenderPointerListener#d9fec NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) behavior: deferToChild listeners: down child with index 3: RenderIndexedSemantics#7cad9 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: index=3; layoutOffset=285.0 constraints: BoxConstraints(w=390.0, h=95.0) semantic boundary size: Size(390.0, 95.0) index: 3 child: RenderRepaintBoundary#6e0bd NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) layer: OffsetLayer#cacc4 engine layer: OffsetEngineLayer#8785f offset: Offset(0.0, 310.0) size: Size(390.0, 95.0) metrics: 83.3% useful (1 bad vs 5 good) diagnosis: this is a useful repaint boundary and should be kept child: RenderSemanticsGestureHandler#0f21d NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) gestures: long press child: RenderPointerListener#90d32 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) behavior: deferToChild listeners: down child with index 4: RenderIndexedSemantics#98e3a NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: index=4; layoutOffset=380.0 constraints: BoxConstraints(w=390.0, h=95.0) semantic boundary size: Size(390.0, 95.0) index: 4 child: RenderRepaintBoundary#4b651 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) layer: OffsetLayer#4d349 engine layer: OffsetEngineLayer#3ac9d offset: Offset(0.0, 405.0) size: Size(390.0, 95.0) metrics: 83.3% useful (1 bad vs 5 good) diagnosis: this is a useful repaint boundary and should be kept child: RenderSemanticsGestureHandler#d08c0 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) gestures: long press child: RenderPointerListener#4d447 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) behavior: deferToChild listeners: down child with index 5: RenderIndexedSemantics#3c29c NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: index=5; layoutOffset=475.0 constraints: BoxConstraints(w=390.0, h=95.0) semantic boundary size: Size(390.0, 95.0) index: 5 child: RenderRepaintBoundary#95d2d NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) layer: OffsetLayer#0a5f6 engine layer: OffsetEngineLayer#48bb1 offset: Offset(0.0, 500.0) size: Size(390.0, 95.0) metrics: 83.3% useful (1 bad vs 5 good) diagnosis: this is a useful repaint boundary and should be kept child: RenderSemanticsGestureHandler#9d4f2 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) gestures: long press child: RenderPointerListener#41da2 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) behavior: deferToChild listeners: down child with index 6: RenderIndexedSemantics#97f8c NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: index=6; layoutOffset=570.0 constraints: BoxConstraints(w=390.0, h=95.0) semantic boundary size: Size(390.0, 95.0) index: 6 child: RenderRepaintBoundary#43698 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) layer: OffsetLayer#4c73b engine layer: OffsetEngineLayer#cf9c5 offset: Offset(0.0, 595.0) size: Size(390.0, 95.0) metrics: 83.3% useful (1 bad vs 5 good) diagnosis: this is a useful repaint boundary and should be kept child: RenderSemanticsGestureHandler#a439c NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) gestures: long press child: RenderPointerListener#c1b95 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) behavior: deferToChild listeners: down child with index 7: RenderIndexedSemantics#af472 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: index=7; layoutOffset=665.0 constraints: BoxConstraints(w=390.0, h=95.0) semantic boundary size: Size(390.0, 95.0) index: 7 child: RenderRepaintBoundary#af250 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) layer: OffsetLayer#45ab6 engine layer: OffsetEngineLayer#f6a96 offset: Offset(0.0, 690.0) size: Size(390.0, 95.0) metrics: 83.3% useful (1 bad vs 5 good) diagnosis: this is a useful repaint boundary and should be kept child: RenderSemanticsGestureHandler#aac55 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) gestures: long press child: RenderPointerListener#428a8 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(w=390.0, h=95.0) size: Size(390.0, 95.0) behavior: deferToChild listeners: down ════════════════════════════════════════════════════════════════════════════════ Reloaded 67 of 2009 libraries in 683ms.

你知道为什么没有使用热重载一切正常吗?如何修复这样的错误?我试图删除 itemExtend,这样就可以避免错误了。但是没有 itemExtend 时,我的 ListView 就会出现一些闪烁情况,看起来像是顺序改变或者其他问题。这很难看。因此,我需要 itemExtend 来解决它。
如果您需要更好地查看代码上下文,我可以给您发送整个文件的代码。顺便说一下,还没有像在构建方法中处理数据这样的函数。这是一个旧项目,我正在全面重写它。但是这些事情并不负责错误。有趣的是,当我移除 "itemExtend" 时,错误就不会出现。这怎么可能呢?
class GuestGuestbookContent extends StatelessWidget {
  GuestGuestbookContent({
    Key key,
  }) : super(key: key);

  GuestbooksController get guestbooksController => Get.find();
  EntriesController get entriesController => Get.find();
  UsersController get usersController => Get.find();

  @override
  Widget build(BuildContext context) {
    return SliverToBoxAdapter(
      child: Container(
        padding: EdgeInsets.only(bottom: 50, top: 50),
        alignment: Alignment.center,
        child: entriesController.obx((state) {
          return Column(
            children: [
              Container(
                child: MixinBuilder(
                  initState: (_) async {
                    await entriesController.checkGuestbookForUserEntries(
                        guestbooksController.currentGuestbook.value.id);
                  },
                  builder: (_) {
                    if (entriesController.hasUserEntry.value == true) {
                      return Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Container(
                            padding:
                                const EdgeInsets.only(left: 25.0, right: 25),
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
                              children: [
                                Text("your_entries",
                                        style: Get.theme.textTheme.headline4)
                                    .tr(),
                                IconButton(
                                    alignment: Alignment.centerRight,
                                    padding: EdgeInsets.all(0),
                                    icon: Icon(
                                      entriesController.showOwnEntries.value ==
                                              false
                                          ? CupertinoIcons.arrow_down
                                          : CupertinoIcons.arrow_up,
                                      color: Get.theme.colorScheme.primary,
                                      size: 20,
                                    ),
                                    onPressed: () => entriesController
                                            .showOwnEntries.value =
                                        !entriesController.showOwnEntries.value)
                              ],
                            ),
                          ),
                          entriesController.showOwnEntries.value == true
                              ? _buildUserEntries()
                              : Container(),
                          SizedBox(height: 15),
                        ],
                      );
                    } else {
                      bool isOpen = true;
                      DateTime startDate;
                      if (guestbooksController
                              .currentGuestbook.value.startDate !=
                          null) {
                        startDate = DateTime.parse(guestbooksController
                            .currentGuestbook.value.startDate);

                        isOpen = startDate.isAtSameMomentAs(DateTime.now()) ||
                            startDate.isBefore(DateTime.now());
                      }

                      if (isOpen) {
                        return _buildAddEntryButton();
                      } else {
                        return Container(
                          child: Column(
                            children: [
                              Image.asset("assets/animations/clock.gif",
                                  width:
                                      context.isTablet ? 400 : Get.width / 2),
                              SizedBox(
                                height: 15,
                              ),
                              Text("guestbook_opens_at").tr(),
                              SizedBox(height: 5),
                              Text(
                                  DateFormat(tr("date_format"))
                                      .format(startDate),
                                  style: Get.theme.textTheme.headline1)
                            ],
                          ),
                        );
                      }
                    }
                  },
                ),
              ),

              // Alle Einträge
              guestbooksController.currentGuestbook.value.isPublic == true ||
                      _isModerator() == true
                  ? _buildAllEntriesContainer()
                  : Container(),
            ],
          );
        }, onLoading: LoadingSpinner()),
      ),
    );
  }

  bool _isModerator() {
    return usersController.userIsModerator(
        userID: usersController.ownUser.value.uid,
        guestbook: guestbooksController.currentGuestbook.value);
  }

  CupertinoButton _buildAddEntryButton() {
    return CupertinoButton(
        child: Column(
          children: [
            Icon(
              Icons.add,
              size: 50,
            ),
            Text(
              "create_entry",
              style:
                  TextStyle(color: Get.theme.colorScheme.primary, fontSize: 20),
            ).tr(),
            SizedBox(height: 25),
          ],
        ),
        onPressed: () => Get.toNamed("writeNewEntry"));
  }

  ListView _buildUserEntries() {
    return ListView.builder(
        shrinkWrap: true,
        padding: EdgeInsets.only(top: 0, bottom: 10),
        physics: ClampingScrollPhysics(),
        itemCount: entriesController.userEntriesData.length,
        itemBuilder: (BuildContext context, int index) {
          final Entry entry = entriesController.userEntriesData[index];

          // Manage description
          String entryContent = "";
          List entryContentInput = [];
          if (entry.content != null) {
            final parsedContent = jsonDecode(entry.content);
            if (parsedContent != null) {
              for (int i = 0; i < parsedContent.length; i++) {
                entryContentInput.add(parsedContent[i]["insert"]);
              }
              entryContent = entryContentInput.join("").toString();
            }
          }

          return GestureDetector(
            onLongPress: () {
              _userEntryOptions(entry);
            },
            child: GuestListTile(
              entry: entry,
              description: entryContent != null && entryContent.isNotEmpty
                  ? entryContent
                  : tr("no_text_added"),
              owner: entry.owner,
              hasImages: entry.images != null && entry.images.isNotEmpty,
              hasVideos: entry.videos != null && entry.videos.isNotEmpty,
              hasPainting:
                  entry.paintingImage != null && entry.paintingImage.isNotEmpty,
            ),
          );
        });
  }

  Container _buildAllEntriesContainer() {
    return Container(
      child: MixinBuilder(
        builder: (EntriesController controller) {
          if (controller.guestbookEntriesWithoutOwn.length > 0) {
            return Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Padding(
                  padding: const EdgeInsets.only(left: 25.0, right: 25),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Text("entries_from_all_guests",
                              style: Get.theme.textTheme.headline4)
                          .tr(),
                      CircleAvatar(
                        radius: 10,
                        backgroundColor: Get.theme.colorScheme.primary,
                        child: Text(
                            controller.guestbookEntriesWithoutOwn.length
                                .toString(),
                            style: TextStyle(
                                fontSize: 10,
                                color: Get.theme.colorScheme.background)),
                      )
                    ],
                  ),
                ),
                _buildAllEntries(controller.guestbookEntriesWithoutOwn),
              ],
            );
          } else {
            return Container();
          }
        },
      ),
    );
  }

  Widget _buildAllEntries(List<Entry> entries) {
    if (entries != null && entries.isNotEmpty) {
      return ListView.builder(
          padding: EdgeInsets.only(top: 10, bottom: 10),
          physics: ClampingScrollPhysics(),
          shrinkWrap: true,
          itemExtent: 95,
          itemCount: entries.length,
          itemBuilder: (BuildContext context, int index) {
            Entry entry;
            if (entries.length > 0) {
              entry = entries[index];

              // Manage description
              String entryContent = "";
              List entryContentInput = [];
              if (entry.content != null) {
                final parsedContent = jsonDecode(entry.content);
                if (parsedContent != null) {
                  for (int i = 0; i < parsedContent.length; i++) {
                    entryContentInput.add(parsedContent[i]["insert"]);
                  }
                  entryContent = entryContentInput.join("").toString();
                }
              }

              return GestureDetector(
                onLongPress: () async {
                  final userID = await getUid();
                  if (usersController.userIsModerator(
                          userID: userID,
                          guestbook:
                              guestbooksController.currentGuestbook.value) ==
                      true) {
                    _userEntryOptions(entry);
                  }
                },
                child: GuestListTile(
                  entry: entry,
                  description: entryContent != null &&
                          entryContent.isNotEmpty &&
                          entryContent != "\n"
                      ? entryContent
                      : tr("no_content"),
                  owner: entry.owner,
                  hasImages: entry.images != null && entry.images.isNotEmpty,
                  hasVideos: entry.videos != null && entry.videos.isNotEmpty,
                  hasPainting: entry.paintingImage != null &&
                      entry.paintingImage.isNotEmpty,
                ),
              );
            } else {
              return Container();
            }
          });
    } else {
      return Container();
    }
  }

  void _userEntryOptions(Entry entry) {
    Get.bottomSheet(CupertinoActionSheet(
      actions: [
        CupertinoActionSheetAction(
          onPressed: () {
            Get.back();
            _deleteUserEntryConfirmation(entry);
          },
          child: Text("delete_this_entry").tr(),
          isDestructiveAction: true,
        )
      ],
    ));
  }

  void _deleteUserEntryConfirmation(Entry entry) {
    Get.dialog(CupertinoAlertDialog(
      title: Text("delete_my_entry_desc").tr(),
      actions: [
        CupertinoDialogAction(
          child: Text("yes_delete_entry").tr(),
          isDestructiveAction: true,
          onPressed: () {
            Get.back();
            _deleteUserEntry(entry);
          },
        ),
        CupertinoDialogAction(
          child: Text("no_not_delete_entry").tr(),
          onPressed: () {
            Get.back();
          },
        )
      ],
    ));
  }

  void _deleteUserEntry(Entry entry) async {
    await entriesController.deleteEntireUserEntry(entry);
    await MySnackbar()
        .createSnackbar(message: tr("entry_deleted_successfully"), seconds: 2);
  }
}

顺便说一下:我正在使用getx包进行状态管理。这就是为什么我可以使用Stateless widget的原因。


热重载类似于setState和重建小部件,我认为在热重载后某些内容变为空了。 - anggadaz
请问您能否添加GuestListTile()的代码?如果无法在此处分享,请尝试将GuestListTile()替换为普通容器和文本,然后再次检查一下? - ABV
嗨@ABV,我已经向应用程序添加了更多代码。我还尝试使用简单的文本小部件而不是GuestListTile()。但结果相同。 - Vueer
4个回答

0
你没有提供很多代码,但也许你应该尝试用 Expanded Widget 包装你的 ListView.builder? :)
然后你的代码会变成这样:
return Expanded(
 child: ListView.builder(
   padding: EdgeInsets.only(top: 25, bottom: 20),
   shrinkWrap: true,
   itemExtent: 95,
   physics: ClampingScrollPhysics(),
   itemCount: entriesController.guestbookEntries.length,
   itemBuilder: (BuildContext context, int index) {

     return GestureDetector(
       onLongPress: () async {
         // Some stuff
       },
       child: GuestListTile()
     );
   },
));

Expanded小部件会占用可用空间,如果在ColumnRow中使用,则非常方便 - 您可以在Flutter - Expanded中了解更多信息。


非常感谢,@IvanTheDevil,我已经尝试了扩展部件,但不起作用(相同结果)。我在上面添加了更多的代码以获得更好的视图。有趣的是,当包括“itemExtent”时,控制台中的错误才会出现。顺便说一下:该应用程序按预期工作。错误只显示在控制台中。 - Vueer

0
使用这个:你的问题将会得到解决。
        return Container(
    height: double.maxfinite;

             child:SingleChildScrollView(
         child: ListView.builder(
               padding: EdgeInsets.only(top: 25, bottom: 20),
               shrinkWrap: true,
               itemExtent: 95,
               physics: NeverScrollableScrollPhysics(),
               itemCount: entriesController.guestbookEntries.length,
               itemBuilder: (BuildContext context, int index) {
            
                 return GestureDetector(
                   onLongPress: () async {
                     // Some stuff
                   },
                   child: GuestListTile()
                 );
               },
            )));

我已经编辑了我的回答,请检查一下。 - Tasnuva Tavasum oshin
你需要在ListView中添加控制器。 - Tasnuva Tavasum oshin
是的。ListView需要一个ScrollController(),但这个控制器没有获取总ListView高度的方法。 - Vueer
itemExtent: 95 * entriesController.guestbookEntries.length; 你将获得高度 - Tasnuva Tavasum oshin
正如我所说,这似乎更像是一种解决方法而不是真正的解决方案。我认为最好的方式是寻找解决问题本身的方法。原则上,列表应该能够工作,但热重载后却不能正常工作,这必定有原因。 - Vueer
显示剩余5条评论

0

使用命令 flutter clean 重新构建应用程序。


嗨@Shamil,这是什么原因?但不幸的是,错误仍在显示,即使在“flutter clean”之后:( - Vueer

0

当你进行热重载时,似乎你的entriesController变量中的guestbookEntries是空的。如果值为null,则显示一些加载指示器,然后在不为null时显示ListView

由于没有控制器类代码,因此你的小部件并没有显示任何内容。


嗨 :) 对于控制器,我使用StateMixin仅在加载完成后显示数据。我已经进行了双重检查。此外,在刷新后,我得到了以下guestbookEntries.entriesController的打印输出:flutter: [Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry', Instance of 'Entry'] - Vueer
所以数据不为空。另外一个问题是:为什么没有itemExtent值也能正常工作? - Vueer
如果itemExtent非空,ListView将强制子项在滚动方向上具有给定的范围。 - Alann Maulana

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接