Issues with Flutter state

Issue

This is an experiment with Flutter. I was trying to create a paragraph generator in Flutter. Made a UI

enter image description here

Loaded the data from a List<String>.

data.dart

class MyData {
  static final List<String> data1 = [
    '0Title Of Page',
    '3Paragraph title One',
    '1First Paragraph Content Of Page',
    '3Paragraph title two',
    '1Second Paragraph Content Of Page',
    '4End of the page line',
  ];
}

I wanted to take the first item from this list to the title of the AppBar(), and it worked. Then I wanted to remove the first item (which is used as the AppBar title) from this list and carry on with the rest of the items in the list to build the body: of the UI.

This works fine when we open this page for the first time. From the next time on, we lose the first item from the list each time we open and close the page. Even though the pages are StatelessWidget we lose the items and finally list running out of items.

Things I tried:

  • I tried changing pages and widgets to StatelessWidget.
  • Tried to override the AppBar back button and pop() the page.
  • Copied List<String> to a new varriable.
  • Used the dispose() method.

Still the same happens. What may be the issues? adding the code below.

main.dart

import 'package:flutter/material.dart';
import 'home_page.dart';
import 'page_one.dart';
import 'page_two.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Paragraph Test',
      initialRoute: '/',
      routes: {
        '/': (context) => HomePage(),
        '/pageone': (context) => PageOne(),
        '/pagetwo': (context) => PageTwo(),
      },
    );
  }
}

home_page.dart

import 'package:flutter/material.dart';
import 'button.dart';
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Page Test'),
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          CButton(
            onTap: () {
              Navigator.pushNamed(context, '/pageone');
            },
            text: 'Page One',
          ),
          CButton(
            onTap: () {
              Navigator.pushNamed(context, '/pagetwo');
            },
            text: 'Page Two',
          ),
        ],
      ),
    );
  }
}

page_one.dart

import 'package:flutter/material.dart';
import 'data.dart';
var weight = FontWeight.normal;
var align = TextAlign.center;
var color = Colors.white60;
var size = 16.0;
String x, y;
class PageOne extends StatelessWidget {
  buildText(String b) {
    x = b.substring(0, 1);
    y = b.substring(1);
    if (x.contains('0')) {
      weight = FontWeight.bold;
      color = Colors.blue;
      size = 18.0;
      align = TextAlign.center;
    } else if (x.contains('2')) {
      weight = FontWeight.normal;
      color = Colors.blue;
      align = TextAlign.right;
      size = 16.0;
    } else if (x.contains('3')) {
      weight = FontWeight.normal;
      color = Colors.blue;
      align = TextAlign.center;
      size = 16.0;
    } else if (x.contains('4')) {
      weight = FontWeight.normal;
      color = Colors.red;
      align = TextAlign.center;
      size = 16.0;
    } else {
      weight = FontWeight.normal;
      color = Colors.white60;
      align = TextAlign.center;
      size = 16.0;
    }
    return y;
  }
  @override
  Widget build(BuildContext context) {
    String title = MyData.data1.first.substring(1);
    MyData.data1.removeAt(0);
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text('$title'),
      ),
      body: Container(
        decoration: BoxDecoration(
          color: Colors.blueGrey,
        ),
        child: Container(
          width: double.infinity,
          height: double.infinity,
          margin: EdgeInsets.all(
            12.0,
          ),
          decoration: BoxDecoration(
            color: Color(0x99000000),
            borderRadius: BorderRadius.circular(10.0),
          ),
          child: SingleChildScrollView(
            padding: EdgeInsets.all(8.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: MyData.data1
                  .map(
                    (item) => Text(
                      buildText(item),
                      textAlign: align,
                      style: TextStyle(
                        color: color,
                        fontWeight: weight,
                        fontSize: size,
                      ),
                    ),
                  )
                  .toList(),
            ),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Text('Page 1'),
        onPressed: () {},
      ),
    );
  }
}

page_two.dart

import 'package:flutter/material.dart';
import 'data.dart';
var weight = FontWeight.normal;
var align = TextAlign.center;
var color = Colors.white60;
var size = 16.0;
String x, y;
class PageTwo extends StatelessWidget {
  buildText(String b) {
    x = b.substring(0, 1);
    y = b.substring(1);
    if (x.contains('0')) {
      weight = FontWeight.bold;
      color = Colors.blue;
      size = 18.0;
      align = TextAlign.center;
    } else if (x.contains('2')) {
      weight = FontWeight.normal;
      color = Colors.blue;
      align = TextAlign.right;
      size = 16.0;
    } else if (x.contains('3')) {
      weight = FontWeight.normal;
      color = Colors.blue;
      align = TextAlign.center;
      size = 16.0;
    } else if (x.contains('4')) {
      weight = FontWeight.normal;
      color = Colors.red;
      align = TextAlign.center;
      size = 16.0;
    } else {
      weight = FontWeight.normal;
      color = Colors.white60;
      align = TextAlign.center;
      size = 16.0;
    }
    return y;
  }
  @override
  Widget build(BuildContext context) {
    String title = MyData.data1.first.substring(1);
    MyData.data1.removeAt(0);
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text('$title'),
      ),
      body: Container(
        decoration: BoxDecoration(
          color: Colors.blueGrey,
        ),
        child: Container(
          width: double.infinity,
          height: double.infinity,
          margin: EdgeInsets.all(
            12.0,
          ),
          decoration: BoxDecoration(
            color: Color(0x99000000),
            borderRadius: BorderRadius.circular(10.0),
          ),
          child: SingleChildScrollView(
            padding: EdgeInsets.all(8.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: MyData.data1
                  .map(
                    (item) => Text(
                      buildText(item),
                      textAlign: align,
                      style: TextStyle(
                        color: color,
                        fontWeight: weight,
                        fontSize: size,
                      ),
                    ),
                  )
                  .toList(),
            ),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Text('Page 2'),
        onPressed: () {},
      ),
    );
  }
}

button.dart

import 'package:flutter/material.dart';
class CButton extends StatelessWidget {
  CButton({this.text, this.onTap});
  final String text;
  final Function onTap;
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        margin: EdgeInsets.all(2.0),
        padding: EdgeInsets.all(16.0),
        decoration: BoxDecoration(color: Colors.blue),
        child: Text(
          '$text',
          style: TextStyle(color: Colors.white),
        ),
      ),
    );
  }
}

Solution

data1 is static variable in MyData class. So its kind of global variable with namespace MyData. So every time you do MyData.data1.removeAt(0); will affect the same memory(or object).

For your case try this,

class MyData {
  static List<String> get data1 => [
    '0Title Of Page',
    '3Paragraph title One',
    '1First Paragraph Content Of Page',
    '3Paragraph title two',
    '1Second Paragraph Content Of Page',
    '4End of the page line',
  ];
}
class PageOne extends StatelessWidget {
  buildText(String b) {
    x = b.substring(0, 1);
    y = b.substring(1);
    if (x.contains('0')) {
      weight = FontWeight.bold;
      color = Colors.blue;
      size = 18.0;
      align = TextAlign.center;
    } else if (x.contains('2')) {
      weight = FontWeight.normal;
      color = Colors.blue;
      align = TextAlign.right;
      size = 16.0;
    } else if (x.contains('3')) {
      weight = FontWeight.normal;
      color = Colors.blue;
      align = TextAlign.center;
      size = 16.0;
    } else if (x.contains('4')) {
      weight = FontWeight.normal;
      color = Colors.red;
      align = TextAlign.center;
      size = 16.0;
    } else {
      weight = FontWeight.normal;
      color = Colors.white60;
      align = TextAlign.center;
      size = 16.0;
    }
    return y;
  }

  @override
  Widget build(BuildContext context) {
    final data1 = MyData.data1;
    String title = data1.first.substring(1);
    data1.removeAt(0);
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text('$title'),
      ),
      body: Container(
        decoration: BoxDecoration(
          color: Colors.blueGrey,
        ),
        child: Container(
          width: double.infinity,
          height: double.infinity,
          margin: EdgeInsets.all(
            12.0,
          ),
          decoration: BoxDecoration(
            color: Color(0x99000000),
            borderRadius: BorderRadius.circular(10.0),
          ),
          child: SingleChildScrollView(
            padding: EdgeInsets.all(8.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: data1
                  .map(
                    (item) => Text(
                      buildText(item),
                      textAlign: align,
                      style: TextStyle(
                        color: color,
                        fontWeight: weight,
                        fontSize: size,
                      ),
                    ),
                  )
                  .toList(),
            ),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Text('Page 1'),
        onPressed: () {},
      ),
    );
  }
}

Answered By – Crazy Lazy Cat

Answer Checked By – Mary Flores (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *