英文:
How to solve range error in growable list?
问题
在调用getUserById()函数时一切正常,可变字符串工作正常,但当我在文本小部件内使用相同的变量时,它会显示RangeError。问题仅发生在我尝试在build方法内使用名为dataAsString的可变字符串列表时。
以下是错误的代码。转到我已经注释错误行的Scaffold
import 'package:Healthwise/helpers/user.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import '../helpers/backEnd.dart';
import '../helpers/frontEnd.dart';
class ResultPage extends StatefulWidget {
  const ResultPage({Key? key}) : super(key: key);
  @override
  State<ResultPage> createState() => _ResultPageState();
}
class _ResultPageState extends State<ResultPage> {
  String objectToString = '';
  String e = '';
  //这个变量正在创建问题...
  // 我已经尝试使用final而不是var,但没有效果。
  var dataAsString = <String>[];
  @override
  void initState() {
    super.initState();
    getUserById();
  }
  getUserById() {
    final String id = itemName;
    userRef.doc(id).get().then((DocumentSnapshot doc) {
      objectToString = doc.data().toString();
      String temp = '';
      int i = 1;
      bool end = false;
      while (objectToString[i] != '}') {
        if (objectToString[i - 1] == ' ' && objectToString[i - 2] == ':') {
          while (objectToString[i] != ',' && !end) {
            temp += objectToString[i];
            if (objectToString[i + 1] != '}') {
              i++;
            } else {
              end = true;
            }
          }
          dataAsString.add(temp);
          temp = '';
          print("The code below this line prints everything perfectly");
          print(dataAsString.length);
          print(dataAsString[0]);
        }
        i++;
      }
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(backgroundColor: primary_color, title: Text("Apple")),
      body: Container(
        child: Column(children: [
          ListTile(
            title: Text(dataAsString[0]),
          ),
          ListTile(
            title: Text(dataAsString[1]),
          ),
          ListTile(
            title: Text(dataAsString[2]),
          ),
        ]),
      ),
    );
  }
}
请注意,dataAsString 列表是在getUserById()方法中异步填充的,所以在初始渲染时可能为空,因此需要确保在使用它之前检查其是否为空或添加适当的空处理。
英文:
When I am calling getUserById() function everything works fine and the growable string works fine but when I use the same variable inside a text widget then it shows RangeError.
The problem is occuring only when I try to use a growable list of string named as dataAsString inside the build.
Here is the Code with Error. Go to the scaffold where I have commented the line of error
import 'package:Healthwise/helpers/user.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import '../helpers/backEnd.dart';
import '../helpers/frontEnd.dart';
class ResultPage extends StatefulWidget {
const ResultPage({Key? key}) : super(key: key);
@override
State<ResultPage> createState() => _ResultPageState();
}
class _ResultPageState extends State<ResultPage> {
// String docId = '';
String objectToString = '';
String e = '';
//This variable is creating the problem...
// I have tried this by using a final instead of var, but nothing worked.
var dataAsString = <String>[];
@override
void initState() {
super.initState();
// getUsers();
getUserById();
}
getUserById() {
final String id = itemName;
userRef.doc(id).get().then((DocumentSnapshot doc) {
// final x = doc.data();
// docId= doc.id;
objectToString = doc.data().toString();
String temp = '';
// print(doc.data());
// print(doc.id);
int i = 1;
// int j = 0;
bool end = false;
//We are just parsing the object into string.
while (objectToString[i] != '}') {
if (objectToString[i - 1] == ' ' && objectToString[i - 2] == ':') {
while (objectToString[i] != ',' && end != true) {
// print(z[i]);
temp += objectToString[i];
if (objectToString[i + 1] != '}') {
i++;
} else {
end = true;
}
}
//Here I add all the strings to list...
// This line works fine.
dataAsString.add(temp);
temp = '';
// j++;
print("The code below this line prints everything perfectly");
print(dataAsString.length);
print(dataAsString[0]);
}
i++;
}
// print(dataAsString[0]);
// print(dataAsString[1]);
// print("+++++++++++");
// print(dataAsString[2]);
// for (var k in dataAsString) {
//   print(k);
// }
// print(dataAsString);
// setState(() {});
});
}
// getUsers() {
//   userRef.get().then((QuerySnapshot snapshot) {
//     snapshot.docs.forEach((DocumentSnapshot doc) {
//       print(doc.data());
//       print(doc.id);
//       print(doc.exists);
//     });
//   });
// }
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(backgroundColor: primary_color, title: Text("Apple")),
body: Container(
child: Column(children: [
ListTile(
//The problem arises here and the app do not crash if I run the same code with just a //string in place of dataAsString[0]
title: Text(dataAsString[0]),
),
ListTile(
title: Text(dataAsString[1]),
),
ListTile(
title: Text(dataAsString[2]),
),
]),
),
);
}
}
答案1
得分: 1
你不能在dataAsString上有数据,因为你正在使用.then来获取数据。你可以进行值检查,如下:
Text(dataAsString.isNotEmpty ? dataAsString[0] : "0 是空的"),
Text(dataAsString.length > 2 ? dataAsString[1] : "1 索引为空"),
Text(dataAsString.length > 3 ? dataAsString[2] : "第三个项目为空"),
英文:
You cant have data on dataAsString because you are using future(.then) on fetching data. You can do value check like
Text( dataAsString.isNotEmpty? dataAsString[0]: "0 is empty"),
Text( dataAsString.length>2? dataAsString[1]: "1 index is empty"),
Text( dataAsString.length>3? dataAsString[2]: "3rd item is empty"),
答案2
得分: 1
因为您的 dataAsString 在第一次渲染 Flutter 时还没有准备好。因此,您需要等待 getUserById 完成以访问 dataAsString 的值。
您可以使用 builder 来以可读的方式检查数据是否准备就绪。
Builder(
  builder: (context) {
    if (dataAsString.length >= 2) {
      return Column(children: [
        ListTile(
          title: Text(dataAsString[0]),
        ),
        ListTile(
          title: Text(dataAsString[1]),
        ),
        ListTile(
          title: Text(dataAsString[2]),
        ),
      ]);
    } else {
      return const Center(
        child: CircularProgressIndicator(),
      );
    }
  },
),
警告:这将有效,因为在完成异步任务后,您调用了 setState。
英文:
It's cause your dataAsString ins't ready on first Flutter rendered frame. So, you need to wait for the getUserById finish to access the dataAsString values.
You can use a builder to check if the data is ready in a readable way.
Builder(
  builder: (context) {
    if (dataAsString.length >= 2) {
      return Column(children: [
        ListTile(
          title: Text(dataAsString[0]),
        ),
        ListTile(
          title: Text(dataAsString[1]),
        ),
        ListTile(
          title: Text(dataAsString[2]),
        ),
      ]);
    } else {
      return const Center(
        child: CircularProgressIndicator(),
      );
    }
  },
),
Warning: it'll work cause you're calling setState when you finish the async task.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。



评论