Why ListView.builder() not working after json fetch

I am trying to load the JSON from a local variable in my class file and convert the JSON to a list of objects using PODO class but I don't know why the list isn't getting generated. I am so much frustrated. Please help me where I am doing wrong.

I have tried every possible way by manipulating the code, even the same code works for a different JSON format with its PODO class.

Thank you.

Flutter class source code:

import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class Demo extends StatefulWidget {
  @override
  _Demo createState() => _Demo();
}

class _Demo extends State<Demo> {
  final localJson = '''
      [
        {
            "message": "Some message here 1"
        },
        {
            "message": "Some message here 2"
        },
        {
            "message": "Some message here 3"
        }
      ]
      ''';

  Widget getCommentItem({@required PodoClass item}) {
    return Text(item.message);
  }

  Future<List<PodoClass>> fetchComments() async {
    return compute(parseJson, localJson);
  }

  List<PodoClass> parseJson(String responseBody) {
    final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();

    return parsed.map<PodoClass>((json) => PodoClass.fromJson(json)).toList();
  }

  Widget _bodyBuild({@required List<PodoClass> items}) {
    return ListView.builder(
        physics: BouncingScrollPhysics(),
        padding: EdgeInsets.symmetric(vertical: 20, horizontal: 20),
        itemCount: items.length,
        itemBuilder: (BuildContext ctxt, int index) {
          return getCommentItem(item: items[index]);
        });
  }

  Widget body() {
    return FutureBuilder<List<PodoClass>>(
      future: fetchComments(),
      builder: (context, snapshot) {
        if (snapshot.hasError) print(snapshot.error);

        return snapshot.hasData
            ? _bodyBuild(items: snapshot.data)
            : Center(child: Text('Loading..'));
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            centerTitle: false,
            title: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    "Comments",
                  ),
                  Text("Battle ID", style: TextStyle(fontSize: 12))
                ])),
        body: body());
  }
}

// podo class
class PodoClass {
  String message;

  PodoClass({this.message});

  PodoClass.fromJson(Map<String, dynamic> json) {
    message = json['message'];
  }
}

2 answers

  • answered 2019-12-09 13:20 Genchi Genbutsu

    you must move parseJson function outside the class it should be top level function

    https://api.flutter.dev/flutter/foundation/compute.html

    The callback argument must be a top-level function, not a closure or an instance or static method of a class.

  • answered 2019-12-09 14:09 Amazing Aidan

    The compute does not work in this case, simply call the function. I've included a delay which may help you with testing.

    import 'dart:convert';
    import 'package:flutter/foundation.dart';
    import 'package:flutter/material.dart';
    
    class Demo extends StatefulWidget {
      @override
      _Demo createState() => _Demo();
    }
    
    class _Demo extends State<Demo> {
      final localJson = '''
            [
              {
                  "message": "Some message here 1"
              },
              {
                  "message": "Some message here 2"
              },
              {
                  "message": "Some message here 3"
              }
            ]
            ''';
    
      Widget getCommentItem({@required PodoClass item}) {
        return Text(item.message);
      }
    
      Future<List<PodoClass>> fetchComments() async {
        await Future.delayed(Duration(seconds: 5));
        return parseJson(localJson);
      }
    
      List<PodoClass> parseJson(String responseBody) {
        final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
    
        return parsed.map<PodoClass>((json) => PodoClass.fromJson(json)).toList();
      }
    
      Widget _bodyBuild({@required List<PodoClass> items}) {
        return ListView.builder(
            physics: BouncingScrollPhysics(),
            padding: EdgeInsets.symmetric(vertical: 20, horizontal: 20),
            itemCount: items.length,
            itemBuilder: (BuildContext ctxt, int index) {
              return getCommentItem(item: items[index]);
            });
      }
    
      Widget body() {
        return FutureBuilder<List<PodoClass>>(
          future: fetchComments(),
          builder: (context, snapshot) {
            if (snapshot.hasError) print(snapshot.error);
    
            return snapshot.hasData
                ? _bodyBuild(items: snapshot.data)
                : Center(child: Text('Loading..'));
          },
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
                centerTitle: false,
                title: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Text(
                        "Comments",
                      ),
                      Text("Battle ID", style: TextStyle(fontSize: 12))
                    ])),
            body: body());
      }
    }
    
    // podo class
    class PodoClass {
      String message;
    
      PodoClass({this.message});
    
      PodoClass.fromJson(Map<String, dynamic> json) {
        message = json['message'];
      }
    }