Flutter Getting data from the api

Viewed 251

Im having problems receiving data from the api, i a class and a function and a class to use the data but im getting null, i used the function from a class to the other in a FutureBuilder. When i get to the screen where the data is trying to be fetched im just getting the circular progress indicator and in the debug is saying Null is not a subtype of String, i tried looking for the problem but i couldn't fix it, the problem might be when im trying to use the function to the other class in the other file, any help would be much appreciated, if someone could implement his answer on the code i send it would be even more helpful.

class LoginData {
  final String loginPhoneNumber;
  final String loginPassword;

  LoginData({
    required this.loginPhoneNumber,
    required this.loginPassword,
  });

  factory LoginData.fromJson(Map<String, dynamic> json) {
    return LoginData(
      loginPhoneNumber: json['phoneNumber'],
      loginPassword: json['lastName']
    );
  }
}

// function

buildSwipeButton() {
    return MenuPage(
      sendData: fetchLoginData(),
    );
  }

  Future<List<LoginData>> fetchLoginData() async {
    var url = 'https://dev.api.wurk.skyver.co/api/employees';

    String basicAuth = 'Basic ' +
        base64Encode(
          utf8.encode('${emailController.text}:${passwordController.text}'),
        );
    var response = await http.get(
      Uri.parse(url),
      headers: <String, String>{'authorization': basicAuth},
    );
    print(response.body);

    if (response.statusCode == 200) {
      print(response.statusCode);
      List data1 = json.decode(utf8.decode(response.bodyBytes));
      return data1.map((data) => LoginData.fromJson(data)).toList();
    } else {
      throw Exception('Failed to load LoginData');
    }
  }

// the other class that im trying to use the data from

class MenuPage extends StatefulWidget {
  const MenuPage({Key? key, Future<List<LoginData>>? sendData, Future<List<LoginData>>?  sendData2}) : super(key: key);

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

class _MenuPageState extends State<MenuPage> {
  final _advancedDrawerController = AdvancedDrawerController();

  void _handleMenuButtonPressed() {
    _advancedDrawerController.showDrawer();
  }

  late LoginData data;
  Future<LoginData>? sendData;

body: FutureBuilder<LoginData>(
          future: sendData,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              LoginData? data1 = snapshot.data;
              data = data1!;
              //print(data.loginPhoneNumber);
              return afterLoginBody();
            } else if (snapshot.hasError) {
              return Text('${snapshot.error}');
            }
            return Center(child: const CircularProgressIndicator());
          },
        ),

afterLoginBody() {
    return ListView.builder(
        itemCount: data.loginPhoneNumber.length,
        itemBuilder: (context, index){
      return ListTile(
        title: Text(''),
      );
    });
  }
}

1 Answers

Though your question was not completely clear as what data type you are expecting from the api. I've tried to make the future builder running on your code and now you can intrepret the response you receive from the server as your needs.

    import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class LoginData {
  final String loginPhoneNumber;
  final String loginPassword;

  LoginData({
    required this.loginPhoneNumber,
    required this.loginPassword,
  });

  factory LoginData.fromJson(Map<String, dynamic> json) {
    return LoginData(
        loginPhoneNumber: json['phoneNumber'], loginPassword: json['lastName']);
  }
}

// function

buildSwipeButton() {
  return MenuPage(
    sendData: fetchLoginData(),
  );
}

Future<List<LoginData>> fetchLoginData() async {
  var url = 'https://dev.api.wurk.skyver.co/api/employees';

  String basicAuth = 'Basic ' +
      base64Encode(
        utf8.encode('${emailController.text}:${passwordController.text}'),
      );
  var response = await http.get(
    Uri.parse(url),
    headers: <String, String>{'authorization': basicAuth},
  );
  // List<Map<String,dynamic>> _dummyResponse = [
  //   {
  //     "id": "0e9ca1b9-6ef3-4e16-93e0-3b4c6c1506c3",
  //     "firstName": "Dibran",
  //     "lastName": "Krasniqi",
  //     "phoneNumber": "049000000",
  //     "idNumber": 1564654
  //   },
  //   {
  //     "id": "0e9ca1b9-6ef3-4e16-93e0-3b4c6c1506c5",
  //     "firstName": "John",
  //     "lastName": "Doe",
  //     "phoneNumber": "049123456",
  //     "idNumber": 65412984
  //   },
  //   {
  //     "id": "0e9ca1b9-6ef3-4e16-93e0-3b4c6c1506e4",
  //     "firstName": "Ajan",
  //     "lastName": "Bikliqi",
  //     "phoneNumber": "049105221",
  //     "idNumber": 456123
  //   }
  // ];

  print(response.body);

  if (response.statusCode == 200) {
    print(response.statusCode);
    List data1 = json.decode(utf8.decode(response.bodyBytes));
    return data1.map((data) => LoginData.fromJson(data)).toList();
  } else {
    throw Exception('Failed to load LoginData');
  }
   



}

// the other class that im trying to use the data from

class MenuPage extends StatefulWidget {
  MenuPage({
    Key? key,
    this.sendData,
    this.sendData2,
  }) : super(key: key);
  Future<List<LoginData>>? sendData;
  Future<List<LoginData>>? sendData2;

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

class _MenuPageState extends State<MenuPage> {
  // final _advancedDrawerController = AdvancedDrawerController();

  // void _handleMenuButtonPressed() {
  //   _advancedDrawerController.showDrawer();
  // }

  late List<LoginData> data;
  Future<LoginData>? sendData;

  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder<List<LoginData>>(
        future: widget.sendData!,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            if (snapshot.data != null) {
              data = snapshot.data!;
            } else {
              data = [];
            }
            //print(data.loginPhoneNumber);
            return afterLoginBody();
          } else if (snapshot.hasError) {
            return Text('${snapshot.error}');
          }
          return Center(child: const CircularProgressIndicator());
        },
      ),
    );
  }

  afterLoginBody() {
    return ListView.builder(
        itemCount: data.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(data[index].loginPhoneNumber),
          );
        });
  }
}
Related