skip to Main Content

am new in flutter an i have a problem with my flutter code
the problem is

NoSuchMethodError: Class ‘String’ has no instance getter ‘logo’ Receiver: "{id: 2, network: MTN, discount: 2, logo: mtncard.png}"

my code is

Future<List<dynamic>> LoadData() async {
  final name = await Hive.box<dynamic>('my_db');
  final result = name.values.toList();
  print(result);
  //print result is gotten perfectly from hive box
  return name.values.toList();
}

SizedBox(
  height: 500,
  child: FutureBuilder<List<dynamic>>(
      future: LoadData(),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (snapshot.data == null) {
          return const Center(
            child: Text('loading'),
          );
        } else {
          return ListView.builder(
            itemCount: snapshot.data.length,
            itemBuilder: (BuildContext context, int index) {
              return ListTile(
                title: Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    SizedBox(
                      width: 20,
                    ),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: [
                        Text(
                          snapshot.data[1].logo.toString(),
                          style: const TextStyle(
                            fontWeight: FontWeight.bold,
                            fontSize: 20,
                            color: Colors.blue,
                          ),
                        ),
                        Icon(
                          Icons.more_horiz,
                          color: Colors.blue,
                        ),
                      ],
                    ),
                  ],
                ),
              );
            },
          );
        }
      }),
);

3

Answers


  1. The error you are recieving means that the snapshot.data[1] is a string not the object you are expecting to contain a logo.

    Login or Signup to reply.
  2. It seems like you are trying to access a property logo on a String object.

    The string you are trying to access is "{id: 2, network: MTN, discount: 2, logo: mtncard.png}" which seems to be a string representation of a Map object. Parse this string to a Map object before trying to access its properties. Your listview should mirror the below:

    import 'dart:convert';
    
    ListView.builder(
      itemCount: snapshot.data.length,
      itemBuilder: (BuildContext context, int index) {
        final itemData = jsonDecode(snapshot.data[index]);
        return ListTile(
          title: Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              SizedBox(
                width: 20,
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  Text(
                    itemData['logo'].toString(),
                    style: const TextStyle(
                      fontWeight: FontWeight.bold,
                      fontSize: 20,
                      color: Colors.blue,
                    ),
                  ),
                  Icon(
                    Icons.more_horiz,
                    color: Colors.blue,
                  ),
                ],
              ),
            ],
          ),
        );
      },
    );
    

    In the above, we decode the string to a Map.

    A better way to handle would be to map the json to a custom class.

    class Provider {
      Provider({
        required this.id,
        required this.network,
        required this.discount,
        required this.logo,
      });
      final String id;
      final String network;
      final int discount;
      final String logo;
    
      factory Provider.fromJson(Map<String, dynamic> data) {
        final id = data['id'] as String;
        final network = data['network'] as String;
        final discount = int.parse(data['discount']);
        final logo = data['logo'] as String;
        return Provider(
          id: id,
          network: network,
          discount: discount,
          logo: logo,
        );
      }
    }
    

    Your listview would look like the below:

    ListView.builder(
      itemCount: snapshot.data.length,
      itemBuilder: (BuildContext context, int index) {
        // Decoding the string to Map
        final Map<String, dynamic> decodedData = jsonDecode(snapshot.data[index]);
        
        // Mapping the Map to Provider object
        final itemData = Provider.fromJson(decodedData);
        
        return ListTile(
          title: Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              SizedBox(
                width: 20,
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  Text(
                    itemData.logo, // Accessing logo from Provider object
                    style: const TextStyle(
                      fontWeight: FontWeight.bold,
                      fontSize: 20,
                      color: Colors.blue,
                    ),
                  ),
                  Icon(
                    Icons.more_horiz,
                    color: Colors.blue,
                  ),
                ],
              ),
            ],
          ),
        );
      },
    );
    
    Login or Signup to reply.
  3. As mentioned in your error message, the snapshot.data return a String object

    "{id: 2, network: MTN, discount: 2, logo: mtncard.png}"

    with quotation mark at the beginning and end.

    A String does not has the logo field you were trying to access. Instead you need to:

    First, turn it into a JSON object, by parsing the String, using jsonDecode

    Import 'dart:convert'; 
      
    final jsonObj = jsonDecode(snapshot.data());
    

    Now you have two choices:
    Directly accessing the logo from the jsonObj

    final logo = jsonObj['logo']
    

    Or, the longer but type-safe way, by creating a class, e.g. named Merchant, specifying the field names and fromJson factory method

    class Merchant {
              Merchant({required this.id, required this.network, required this.discount, required this.logo});
              final String id;
              final String network;
              final int discount;
              final String logo;
        
        factory Merchant.fromJson(Map<String, dynamic> data) {
            final id = data['id'] as String;
            final network = data['network'] as String;
            final discount = int.parse(data['discount'])
            final logo = data['logo'] as String;
            return Merchant(id: id, network: network, discount: discount, logo: logo);
          }
    }
    

    ADDITIONAL NOTE: paste the code above into a .dart file, name it merchant.dart (or sth). For the ease of scalability, I would suggest to store the merchant.dart file in a model folder, under lib folder lib>model>merchant.dart

    Finally, map the JSON object into the Merchant class to create an instance of Merchant

    final Merchant merchant = Merchant.fromJson(jsonObj);
    

    You need to import the merchant.dart file in order to access the Merchant class and fromJson method.

    Now you can safely access the logo field

    final String logo = merchant.logo;
    

    Hope it helps!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search