Flutter incorporate looping variable into widget

Viewed 72

I want to incorporate looping variable into widget. So I have code like this but get an alert [Missing concrete implementation of 'State.build'.] Premise ... Data has been inserted in DB

class Classname extends StatefulWidget {
  Classname({Key key}) : super(key: key);

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

class _ClassnameState extends State<Classname> {
  String test;
  String test2;
  String test3;

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

  void getData() async {
    String path = join(await getDatabasesPath(), 'dbname.db');

    Database database = await openDatabase(path, version: 1,
        onCreate: (Database db, int version) async {
          await db.execute(
              "CREATE TABLE tablename(id INTEGER PRIMARY KEY, test TEXT, test2 TEXT, test3 TEXT)");
        });

    List<Map> result = await database.rawQuery('SELECT * FROM tablename');

    for (Map data in result) {
      test = data['test'];
      test2 = data['test2'];
      test3 = data['test3'];

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SingleChildScrollView(
            child: Container(
              padding: EdgeInsets.all(30),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: <Widget>[
                  Row(
                    mainAxisAlignment: MainAxisAlignment.start,
                    mainAxisSize: MainAxisSize.max,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: <Widget>[
                      Container(
                        child: Text(
                          test,                             
                        ),
                      ),
                      Padding(
                        padding: EdgeInsets.all(15),
                      ),
                      Container(
                        child: Text(
                          test2
                        ),
                      ),
                    ],
                  ),
                  Container(
                    child: Text(
                      test3,                      
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }
  }

I tried other ways, for example, adding List variable = [] and use add method but it's not good because the list didn't become dynamic. Please tell me how to do.

2 Answers

The problem is you haven't provided a build function. If you are a beginner programmer, you have to work on your Object Oriented Programming concepts. Here I just fixed your code. You can't provide a build function in another function. Build function is associated with the State. So, state need to define a function named build. You have actually provided the function in (very) wrong way. Like your code is not making sense to the the compiler. It is compile time error.

As far as for loop incorporating goes you need only to generate the list based on the data, using List.generate or any other method you want like function or loop. Looking at your code looks like you won't get too much of the details. But Enjoy the following code will work

class Classname extends StatefulWidget {
  Classname({Key key}) : super(key: key);

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

class _ClassnameState extends State<Classname> {
  String test;
  String test2;
  String test3;

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

  Future<List<Map>> getData() async {
    String path = join(await getDatabasesPath(), 'dbname.db');

    Database database = await openDatabase(path, version: 1,
        onCreate: (Database db, int version) async {
      await db.execute(
          "CREATE TABLE tablename(id INTEGER PRIMARY KEY, test TEXT, test2 TEXT, test3 TEXT)");
    });

    List<Map> result = await database.rawQuery('SELECT * FROM tablename');
    return result;
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      body: FutureBuilder<List<Map>>(
          future: getData(),
          builder: (context, result) {
            if (result.connectionState == ConnectionState.waiting) {
              return Center(
                  child:
                      CircularProgressIndicator()); //while you are calculating your data show the loading.
            }
            if (!result.hasData) {
              return Center(
                  child: Text(
                      "No Data")); //if there is no data available show the No data message.
            }
            //otherwise we will have some data
            return SingleChildScrollView(
              child: Container(
                padding: EdgeInsets.all(30),
                child: Column(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: List.generate(result.data.length, (index) {
                      var data = result.data[index];
                      test = data['test'];
                      test2 = data['test2'];
                      test3 = data['test3'];
                      return Column(
                        children: [
                          Row(
                            mainAxisAlignment: MainAxisAlignment.start,
                            mainAxisSize: MainAxisSize.max,
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: <Widget>[
                              Container(
                                child: Text(
                                  test,
                                ),
                              ),
                              Padding(
                                padding: EdgeInsets.all(15),
                              ),
                              Container(
                                child: Text(test2),
                              ),
                            ],
                          ),
                          Container(
                            child: Text(
                              test3,
                            ),
                          ),
                        ],
                      );
                    })),
              ),
            );
          }),
    );
  }
}

The reason that you get the error about the missing State.build method is that you have it nested inside your getData method. Move the build() method outside of getData and the error should go away.

Advice for improving your code further would be to move all the logic out of the widget and use a state management solution like Provider or Bloc.

Related