Home > database >  Display a text string and change it dynamically Flutter/Dart
Display a text string and change it dynamically Flutter/Dart

Time:04-14

Basically what i want to do is to display a name taken from a file that contains many others, and after a small delay, the given name changes into another word. The text that i wanna change is inside a Text() widget.

class ReadTextFile extends StatefulWidget {
  const ReadTextFile({Key? key}) : super(key: key);

  @override
  _ReadTextFileState createState() => _ReadTextFileState();
}

/*
 *  Retriving data from file, picking a random word and assign it to dataFromFile
 */

class _ReadTextFileState extends State<ReadTextFile> {

  String dataFromFile = "";
  static List<String> listOne = []; //contains all jobs.txt content, from top to bottom
  int randomIndex = Random().nextInt(1027); //quick fix to "RangeError" thrown by Random().nextInt(listOne.length)

  Future<void> readText() async {
    final String response = await rootBundle.loadString('assets/jobs.txt');
    listOne = response.split(',');
    setState(() {
      dataFromFile = listOne[randomIndex];
    });
  }

  @override
  Widget build(BuildContext context) {
    readText();
    // showRandomJob();
    return Container(child: Center(child: Text(dataFromFile)));
  }
} 

Widget tree:

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final appTitle = 'ListGenerator';

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          foregroundColor: Color.fromARGB(255, 32, 75, 132),
          title: Text(appTitle),
          centerTitle: true,
          backgroundColor: Color.fromARGB(255, 11, 161, 242),
        ),
        body: Column(
          children: const[
             Expanded(
                flex: 1,
                child: SingleChildScrollView(
                  scrollDirection: Axis.vertical,
                  child: ReadTextFile(),
                )),
          ],
        ),
      ),
    );
  }
 
}

As a plus, i'd like to know why passing listOne.length as a parameter to Random.nextInt() generates these 2 errors.

After running a hot restart:

RangeError (max): Must be positive and <= 2^32: Not in inclusive range 1..4294967296:
0
See also: https://flutter.dev/docs/testing/errors

Running a hot reload after a hot restart:

'package:flutter/src/widgets/framework.dart': Failed assertion: line 6205 pos 12: 'child == _child': is not true. See also: https//flutter.dev/docs/testing/errors

CodePudding user response:

Use Timer() inside the initState and move the randomIndex line inside the readText() function

import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class ReadTextFile extends StatefulWidget {
  @override
  _ReadTextFileState createState() => _ReadTextFileState();
}

class _ReadTextFileState extends State<ReadTextFile> {

  String dataFromFile = "";
  static List<String> listOne = [];

  Future<void> readText() async {
    final String response = await rootBundle.loadString('assets/jobs.txt');
    listOne = response.split(',');
    int randomIndex = Random().nextInt(listOne.length);
    setState(() {
      dataFromFile = listOne[randomIndex];
    });
  }

  @override
  void initState() {
    super.initState();
    // change text after 1 sec
    Timer(Duration(seconds: 1), ()=>readText());
  }
  
  @override
  Widget build(BuildContext context) {
    return Container(child: Center(child: Text(dataFromFile)));
  }
}

CodePudding user response:

readText() is a Future method, you need to await before using its data. Next thing is we can't tell what should be the response list. We need to act based on list items.

class _ReadTextFileState extends State<ReadTextFile> {
  String dataFromFile = "";
  static List<String> listOne =
      [];
  Future<void> readText() async {
    final String response = await rootBundle.loadString('assets/jobs.txt');
    listOne = response.split(',');
    setState(() {
      if (listOne.length > 2) {
        dataFromFile = listOne[Random().nextInt(listOne.length - 1)];
      } else if (listOne.length == 1) {
        dataFromFile = listOne.first;
      }
    });
    debugPrint(listOne.toString());
  }

  void initData() async {
    await readText();
  }

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

  @override
  Widget build(BuildContext context) {
    return Container(child: Center(child: Text(dataFromFile)));
  }
}

  • Related