Home > Back-end >  How can I get data from a local json file and create a gridview in Flutter?
How can I get data from a local json file and create a gridview in Flutter?

Time:05-28

I'm trying to make an educational application in Turkish and i want to list the topics on my homepage. I created a sketch of my homepage and i want to print the texts inside the cards by taking the parts named "konuBasligi" from the local json file.

Before sharing the codes, I would like to share the existing design and json file with you:

{
    "bende": {
        "dersler": [{
            "id": 0,
            "dersAdi": "Türkçe"
        }, {
            "id": 1,
            "dersAdi": "Matematik"
        }, {
            "id": 2,
            "dersAdi": "Tarih",
            "konular": [{
                "konuId": 0,
                "konuBasligi": "İslamiyet Öncesi Türk Tarihi",
                "altkonular": [{
                    "altKonuId": 0,
                    "altKonuBasligi": "Giriş",
                    "basliklar": [{
                        "baslikId": 0,
                        "baslikAdi": "Türk Adının Anlamı"
                    }, {
                        "baslikId": 1,
                        "baslikAdi": "İlk Yerleşim Yerleri"
                    }, {
                        "baslikId": 2,
                        "baslikAdi": "Göçler"
                    }]
                }, {
                    "altKonuId": 1,
                    "altKonuBasligi": "İlk Türk Toplulukları ve Devletleri",
                    "basliklar": [{
                        "baslikId": 0,
                        "baslikAdi": "İskitler"
                    }, {
                        "baslikId": 1,
                        "baslikAdi": "Asya Hun Devleti"
                    }, {
                        "baslikId": 2,
                        "baslikAdi": "Avrupa Hun Devleti"
                    }]
                }, {
                    "altKonuId": 2,
                    "altKonuBasligi": "Diğer Türk Toplulukları ve Devletleri",
                    "basliklar": [{
                        "baslikId": 0,
                        "baslikAdi": "Avatarlar"
                    }, {
                        "baslikId": 1,
                        "baslikAdi": "Karluklar"
                    }, {
                        "baslikId": 2,
                        "baslikAdi": "Kırgızlar"
                    }]
                }, {
                    "altKonuId": 3,
                    "altKonuBasligi": "Kültür ve Medeniyet",
                    "basliklar": [{
                        "baslikId": 0,
                        "baslikAdi": "Hükümdarlar"
                    }, {
                        "baslikId": 1,
                        "baslikAdi": "Devlet Yönetimi"
                    }, {
                        "baslikId": 2,
                        "baslikAdi": "Ordu"
                    }]
                }]
            }, {
                "konuId": 1,
                "konuBasligi": "İlk Türk İslam Devletleri"
            }, {
                "konuId": 2,
                "konuBasligi": "Türkiye Tarihi"
            }, {
                "konuId": 3,
                "konuBasligi": "Osmanlı Tarihi"
            }, {
                "konuId": 4,
                "konuBasligi": "Kurtuluş Savaşı"
            }, {
                "konuId": 5,
                "konuBasligi": "Çağdaş Türk ve Dünya Tarihi"
            }]
        }, {
            "id": 3,
            "dersAdi": "Coğrafya"
        }, {
            "id": 4,
            "dersAdi": "Vatandaşlık"
        }, {
            "id": 5,
            "dersAdi": "Genel Kültür"
        }, {
            "id": 6,
            "dersAdi": "Program Geliştirme"
        }, {
            "id": 7,
            "dersAdi": "Rehberlik ve Özel Eğitim"
        }, {
            "id": 8,
            "dersAdi": "Öğretim Yöntem ve Teknikleri"
        }, {
            "id": 9,
            "dersAdi": "Ölçme ve Değerlendirme"
        }, {
            "id": 10,
            "dersAdi": "Öğrenme Psikolojisi"
        }, {
            "id": 11,
            "dersAdi": "Gelişim Psikolojisi"
        }]
    }
}

I think I read the data using "FutureBuilder" and "DefaultAssetBundle" from the video I watched and the articles I read, but I got stuck in the "children" part in "Gridview.count". I couldn't adapt it myself because they usually use "Listview.builder".

The code of the design image I shared contains too many files such as "screens", "utils". For this, I created a file with only the parts related to my question and its contents are as follows:

import 'dart:convert';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());

class MyApp extends StatelessWidget { 
  const MyApp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
  return MaterialApp(
    title: 'Test',
    home: Scaffold(
    appBar: AppBar(
      title: const Text('Gridview From JSON'),
    ),

    body: FutureBuilder(
        future: DefaultAssetBundle.of(context).loadString('data/veri.json'),
        builder: (context, snapshot) {
          var read = json.decode(snapshot.data.toString());
          return GridView.count(
            crossAxisCount: 2,
            padding:
                const EdgeInsets.only(left: 12.0, right: 12.0, top: 8.0),
            scrollDirection: Axis.vertical,
            childAspectRatio: 1,
            physics: const NeverScrollableScrollPhysics(),
            shrinkWrap: true,
            children: [
              Card(
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(16)),
                clipBehavior: Clip.antiAlias,
                color: Colors.blue[200],
              ),
            ],
          );
        }),
  ),
);
}
}

Thank you in advance for your help...

CodePudding user response:

Actually you have to check for state before trying to use data in future builder. Try these -

FutureBuilder(
   future: DefaultAssetBundle.of(context).loadString('data/veri.json'),
   builder: (ctx, snapshot) {
     // Checking if future is resolved
   if (snapshot.connectionState == ConnectionState.done) {
     // If we got an error
   if (snapshot.hasError) {
     return Center(
       child: Text(
        '${snapshot.error} occured',
        style: TextStyle(fontSize: 18),
       ),
    );
    
    // if we got our data
   } else if (snapshot.hasData) {
       // Extracting data from snapshot object
       var read = json.decode(snapshot.data.toString());
      return GridView.count(
        crossAxisCount: 2,
        padding:
            const EdgeInsets.only(left: 12.0, right: 12.0, top: 8.0),
        scrollDirection: Axis.vertical,
        childAspectRatio: 1,
        physics: const NeverScrollableScrollPhysics(),
        shrinkWrap: true,
        children: [
          Card(
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(16)),
            clipBehavior: Clip.antiAlias,
            color: Colors.blue[200],
          ),
        ],
      );
     }
  }

),

Hope it helps.

CodePudding user response:

You have to options:

First Option: is to continue using GridView.count() and for the children you have to just iterate on them in any method, maybe for loop or .map() method.

Let's say you will display the dersler read from the JSON file and you have created a variable to point on them like the following:

var read = json.decode(snapshot.data.toString());
final List dersler = read['dersler'];

Now you can generated the children by iterating over the data,

Example using .map() method:

children: dersler.map((item) {
    return Card(
        shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(16)),
            clipBehavior: Clip.antiAlias,
            color: Colors.blue[200],
        );
    }).toList(),

Example using for loop:

children: [
    for (int i = 0; i < dersler.length; i  )
        Card(
            shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(16)),
            clipBehavior: Clip.antiAlias,
            color: Colors.blue[200],
         )
    ],

Second Option (Suggested) : is to use GridView.builder() instead of using GridView.count() which gives you a bonus of lazy loading the data into memory, which means only the data that is currently visible on the screen would be held in the memory, which is a very good optimization made out of the box by Flutter.

Example:

FutureBuilder(
    future: DefaultAssetBundle.of(context).loadString('data/veri.json'),
        builder: (context, snapshot) {
            var read = json.decode(snapshot.data.toString());
            final List dersler = read['dersler'];
            return GridView.builder(
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2,
              ),
              padding: const EdgeInsets.only(left: 12.0, right: 12.0, top: 8.0),
              scrollDirection: Axis.vertical,
              physics: const NeverScrollableScrollPhysics(),
              shrinkWrap: true,
              itemCount: dersler.length,
              itemBuilder: (BuildContext context, int index) {
                return Card(
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(16)),
                  clipBehavior: Clip.antiAlias,
                  color: Colors.blue[200],
                );
              },
        );
    },
),
  • Related