Flutter - Listview with API JSON

One of the most important in mobile apps  is fetching data from Web API and showing it to a Listviw control. And the good news for Flutter developer, fetching data from Web API so easy. Here we can learn how to fetching data API to Listview.

Implementation

i already create my own Web API and its return data like this :

{
  "ResponseCode": "500",
  "ResponseMessage": "Success",
  "ResponseData": [
    {
      "ID": 1,
      "UserID": "djanuar",
      "UserName": "Januar Aransyah",
      "CheckInDay": "Monday",
      "CheckInDate": "2019-07-01T00:00:00",
      "CheckInWorked": "Worked For 7Hrs 20Min",
      "CheckInStart": "07:00:00",
      "CheckInEnd": "18:00:00",
      "Photo": "C:/inetpub/wwwroot/RELEASE-API/Images/djanuar.jpg"
    }
  ],
  "ValException": null
}

Models

When we work with API data, the first thing that we have to create is model associated with data that will recieve back from API service. We put every field API data in here. Because my JSON data is nested JSON, so we should to create two model for receive our data, first ResultModel and second AttendanceModel.

Here our model look like.

ResultModel.dart

class ResultModel
{
    final String responsecode;
    final String responsemessage ;
    final List responsedata ;

    ResultModel({
      this.responsecode,
      this.responsemessage,
      this.responsedata
    });

    factory ResultModel.fromJSON(Map<String, dynamic> jsonMap) 
    {
      var list = jsonMap['ResponseData'] as List;

      final data = ResultModel( 
        responsecode: jsonMap["ResponseCode"],
        responsemessage: jsonMap["ResponseMessage"],
        responsedata: list);
      return data;
    }

}

AttendanceModel.dart

class AttendanceModel {
  final int id;
  final String userid;
  final String username;
  final String checkinday;
  final String checkindate;
  final String checkinworked;
  final String checkinstart;
  final String checkinend;
  final String photo;

  AttendanceModel.fromJSON(Map<String, dynamic> jsonMap) :
    id = jsonMap['ID'],
    userid = jsonMap['UserID'],
    username = jsonMap['UserName'],
    checkinday = jsonMap['CheckInDay'],
    checkindate = jsonMap['CheckInDate'],
    checkinworked = jsonMap['CheckInWorked'],
    checkinstart = jsonMap['CheckInStart'],
    checkinend = jsonMap['CheckInEnd'],
    photo = jsonMap['Photo']; 
}

ResultModel and AttendanceModel we implemented fromJson function which responsible for take a JSON data and returning to a new Result Model. And in ResultModel contain responsedata as list of AttendanceModel, that’s for handle nested json from API data.

Service

We will create separated service class which main purpose of this class will be invoke endpoint dan to get returning data.

APIService.dart

import 'package:http/http.dart' as http;

class APIService<T> {
  final String url;// = urlHost + 'RELEASE-API/Api/attendance/getdata';
  T Function(http.Response response) parse;

  APIService({this.url, this.parse});  
}

class APIWeb{
  Future<T> load<T>(APIService<T> resource) async {

      final response = await http.get(resource.url);
      if(response.statusCode == 200) {
        return resource.parse(response);
      } else {
        throw Exception('Failed to load data!');
      }
  }
}

This APIWeb return to Future<T>, this allowing us to use service class to call different end point and return data. APIService just simple class which defines url and custome function who will be used to parse JSON data.

Repositories

Next step is repositories, this function for call our API dan will returning to list of AttendanceModel because we just wanna fetching that data. And here code look like below :

AttendanceRepositories.dart

import 'dart:convert';
import 'package:listview_bind_api/APIService.dart';

import 'package:listview_bind_api/AttendanceModel.dart';
import 'package:listview_bind_api/ResultModel.dart';

class AttendanceRepositories{
  final String urlHost = 'http://172.20.10.10/';
  
  static APIService<List<AttendanceModel>> get getData {
    return APIService(
      url:  'http://172.20.10.10/RELEASE-API/Api/attendance/getdata',
      parse: (response) {
        final parsed = json.decode(response.body); 
        final dataJson = ResultModel.fromJSON(parsed);
        return dataJson.responsedata.map((i) => AttendanceModel.fromJSON(i)).toList();
      }
    );
  }
}

AttendanceRepositories containing method which call our APIService will parses response and build to List<AttendanceModel>.

Screen

We create class of widget that will be resposible for displaying all of the data in ListView control, AttendanceScreen will call the method from AttendanceRepositories which return list of data, data will showing when application running or reload, so we need put call method in initState() to handle it, and also we need to define attandance as list inside the class who will put data after we call method at the first time running the application.

So when method been called and attendance list already exist data then ListView will generate their item.

here code below:

import 'package:listview_bind_api/APIService.dart';
import 'package:listview_bind_api/AttendanceModel.dart';
import 'package:flutter/material.dart';
import 'package:listview_bind_api/AttendanceRepositories.dart';
import 'package:listview_bind_api/ResultModel.dart';

import 'AttendanceRepositories.dart';

class AttendanceScreen extends StatefulWidget {
  const AttendanceScreen({Key key}) : super(key: key);
  @override
  _AttendanceScreenState createState() => _AttendanceScreenState();
}
class _AttendanceScreenState extends State<AttendanceScreen>{
  final String urlHost = 'http://172.20.10.10/';
  List<AttendanceModel> _attendance = <AttendanceModel>[];
  ResultModel oResult = ResultModel();

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

  @override
  Widget build(BuildContext context) {
    return ListView.separated(
      separatorBuilder: (context, index) => Divider(
        color: Colors.black,
      ),
      itemCount: _attendance.length,
      itemBuilder: (context, index) {
        return ListTile(
          title: Text(_attendance[index].checkinday),
          leading: Container(
            margin: EdgeInsets.only(left: 6.0),
            child: Image.network(_attendance[index].photo.replaceAll("C:/inetpub/wwwroot/", urlHost), height: 50.0, fit: BoxFit.fill,)
          ),
          trailing: Text(_attendance[index].checkinstart),
          subtitle: Text(_attendance[index].checkinworked),
        );
      },
    );
  }

  void _getData() {
   
    APIWeb().load(AttendanceRepositories.getData).then((attendance) => {
      setState(() => {
        _attendance = attendance
      })
    });
  }  
}

Displaying Data

After all of steps we’ve done, now in main menu we just need to call AttendanceScreen in body.

Main.dart

import 'package:flutter/material.dart';
import 'package:listview_bind_api/AttendanceScreen.dart';
import 'package:listview_bind_api/attendanceModel.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo List View Bind API'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  List<AttendanceModel> _attendances = <AttendanceModel>[];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: AttendanceScreen(),
      floatingActionButton: FloatingActionButton(
        onPressed: null,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

Running the apps.

as result when you running the apps will be look like this.

Flutter - Listview with API JSON

What was you learned, from here:

  1. Using HTTP library to consume API request
  2. Make Api call to return data
  3. Parsing return JSON into model class
  4. Displaying data in a Lisview control
  5. Displaying image network.

For full source code, you can get here.

You can also learn more about Flutter parse JSON data by visit JSON and serialization

Stay tuned for more tutorial, you can check this to see all of flutter tutorials.

HAPPY SHARE.

Advertisements
Share: