我的列表在生成页面上的列表值后未显示在搜索页面上。为什么?

huangapple go评论68阅读模式
英文:

My list is not showing up on search page after generating values for list on page start. Why?

问题

以下是您提供的代码的翻译部分:

我正在使用Flutter制作一个搜索页面。我已经成功添加了搜索栏,但是现在添加相应的列表正在成为一个问题。用户搜索的数据来自一个JSON文件,所以我已经成功地编写了将JSON文件转换为正确的内部数据类型并构造了代码,以便在页面构建之前填充列表。然而,似乎这不起作用,页面在JSON解析完成之前就已经构建了。有关如何继续的任何想法将不胜感激。

我尝试使用initState并将JSON读取功能放在构建函数的开头。这两种方法都没有起作用。我考虑在之前的页面中创建列表并将其传递到搜索页面,但我更愿意在页面本身完成。

以下是我目前为止拥有的页面代码。

// 以下是您提供的Dart代码,我将其翻译为中文以方便理解。

请注意,我只翻译了代码部分,没有包括评论或其他内容。如果您需要进一步的帮助或有其他问题,请随时提问。

英文:

I am making a search page in flutter. I have sucsessfully added the search bar, but now adding the corresponding list is becoming an issue. The data that the user searches is from a json file, so I have sucsessfully programmed converting the json file to the correct internal data type and have stuctured the code so that the list would be filled before the building of the page. However, this seems to be not working and and the page is building before the parsing of the json is complete. Any ideas on how top proceed would be much appreciated.

I have tried using init state and putting the json read fuction in the beginning of the build fuction. Neither of these have worked. I have considered createing the list in a previous page and passing it to the search page, but I would much rather have it done in the page itself.

Below is the code I have for the page as of now.

import 'dart:convert';

import 'package:dnd_app/Models/fighter.dart';
import 'package:dnd_app/Models/monster.dart';
import 'package:flutter/material.dart';
import 'package:dnd_app/constants.dart' as constants;
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:dnd_app/Models/pc.dart';
import 'package:flutter_svg/svg.dart';

class monsterSearch extends StatefulWidget {
  const monsterSearch({super.key});

  @override
  State<monsterSearch> createState() => _monsterSearchState();
}

class _monsterSearchState extends State<monsterSearch> {
  List<Monster> monsters = [];
  int mom = 10;

  @override
  void initState() {
    readJson();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    print(monsters.length);
    return Scaffold(
      appBar: constants.titleBar("Monster Search"),
      backgroundColor: constants.greyGold(),
      body: Column(
        children: [
          searchBar(),
          Expanded(
              child: ListView.builder(
            scrollDirection: Axis.vertical,
            itemCount: monsters.length,
            itemBuilder: (context, index) {
              return Text(monsters[index].name);
            },
          ))
        ],
      ),
    );
  }

  Future<void> readJson() async {
    final String responce =
        await rootBundle.loadString('assets/5e-SRD-Monsters.json');
    final retData = jsonDecode(responce);
    for (var mon in retData) {
      try {
        String sSpeed = mon["speed"];
        sSpeed = sSpeed.substring(0, sSpeed.indexOf(' '));
        monsters.add(Monster(
            mon["name"],
            mon["hit_points"],
            mon["armor_class"],
            mon["strength"],
            mon["constitution"],
            mon["dexterity"],
            mon["intelligence"],
            mon["wisdom"],
            mon["charisma"],
            int.parse(sSpeed)));
      } on Error catch (_) {
        continue;
      } on Exception catch (_) {
        continue;
      }
    }
    print(monsters.length);
  }

  void waitingGame() async {
    await readJson();
  }

  Container searchBar() {
    return Container(
      margin: EdgeInsets.only(top: 40, left: 20, right: 20),
      decoration: BoxDecoration(
          boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.11))]),
      child: TextField(
        decoration: InputDecoration(
            filled: true,
            fillColor: Colors.white,
            hintText: 'Search Monster',
            contentPadding: EdgeInsets.all(15),
            prefixIcon: Padding(
              padding: const EdgeInsets.all(12),
              child: SvgPicture.asset('assets/pictures/icons8-search.svg'),
            ),
            border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(15),
                borderSide: BorderSide.none)),
      ),
    );
  }
}

答案1

得分: 2

你尝试过将以下代码包装在一个FutureBuilder中,其中future将是你的readJson。会像这样:

return FutureBuilder(
      future: viewModel.getStories,
      builder: (context, snapshot) {
        if(snapshot.hasData && snapshot.connectionState == ConnectionState.done) {
          List<Monster> futureBuilderMonsters = snapshot.data as List<Monster>;
          return Expanded ...
        }

        return const Center(
          child: SizedBox(width: 64, height: 64, child: CircularProgressIndicator()),
        );
      },
  );

你的readJson应该返回Future<List<Monster>>,以便FutureBuilder知道何时存在数据。你的“旧”怪物列表可以保留,以防你在其他地方需要它。

英文:

Have you tried to wrap

Expanded(
  child: ListView.builder(
    scrollDirection: Axis.vertical,
    itemCount: monsters.length,
    itemBuilder: (context, index) {
      return Text(monsters[index].name);
    },
  )
)

inside a FutureBuilder where the future will be your readJson.
Would look something like this:

return FutureBuilder(
      future: viewModel.getStories,
      builder: (context, snapshot) {
        if(snapshot.hasData &amp;&amp; snapshot.connectionState == ConnectionState.done) {
          List&lt;Monster&gt; futureBuilderMonsters = snapshot.data as List&lt;Monster&gt;;
          return Expanded ...
        }

        return const Center(
          child: SizedBox(width: 64, height: 64, child: CircularProgressIndicator()),
        );
      },
  );

Your readJson should return Future&lt;List&lt;Monsters&gt;&gt; so the FutureBuilder knows when data is existing. Your "old" Monster list can stay in case you need it somewhere else

huangapple
  • 本文由 发表于 2023年7月11日 04:26:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76657112.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定