Search code examples
flutterrestdartflutter-getxflutter-listview

How can i fetch data from an API using the OBX functionality in flutter


I already tried this code but it doesn't seem to work properly as the Users.value remain empty even after the data has been fetched good from the API ( i printed the http response and it showed the data fetched ) ; The code gives no errors , here is the code in a project : https://github.com/TheChinegami/fetching ; Clone it and try , i'll appreciate the help !

after creating a project with GetCli ( get create project:X) , I created a page called User and it came with a view , controller and binding , I created the UserModel class first :

class User {
  final String id;
  final String name;

  User({required this.id, required this.name});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'],
      name: json['name'],
    );
  }
}

then I edited the Controller :

import 'dart:convert';

import 'package:fetchingtwo/app/modules/User/model/User.model.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;

class UserController extends GetxController {
  final users = <User>[].obs;

  @override
  void onInit() {
    fetchUsers();
    super.onInit();
  }

  Future<void> fetchUsers() async {
    try {
      final response = await http
          .get(Uri.parse('https://jsonplaceholder.typicode.com/users'));

      if (response.statusCode == 200) {
        print(response.body); // this is where I check if the response actually returns anything and it                                does !!

        final List<dynamic> jsonList = json.decode(response.body);
        users.value = jsonList.map((json) => User.fromJson(json)).toList();
      } else {
        // Handle error response
      }
    } catch (e) {
      // Handle error
    }
  }
}

And lastly to show the results I edited the view :

import 'package:flutter/material.dart';

import 'package:get/get.dart';

import '../controllers/user_controller.dart';

class UserView extends GetView<UserController> {
  UserView({Key? key}) : super(key: key);
  final UserController userController = Get.put(UserController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('User List'),
      ),
      body: Obx(() {
        if (userController.users.isEmpty) {
          return const Center(child: CircularProgressIndicator());
        } else {
          return ListView.builder(
            itemCount: userController.users.length,
            itemBuilder: (context, index) {
              final user = userController.users[index];
              return ListTile(
                title: Text(user.name),
              );
            },
          );
        }
      }),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          userController.fetchUsers();
        },
        child: Icon(Icons.refresh),
      ),
    );
  }
}

the problem is after entring the User List page , the UserController.users always remains Empty ;


Solution

  • okay simply i've changed some code on the controller :

    from final users = <User>[].obs;

    to var users = <User>[].obs;

    and i changed the model too :

    from :

    class User {
      final String id;
      final String name;
    
      User({required this.id, required this.name});
    
      factory User.fromJson(Map<String, dynamic> json) {
        return User(
          id: json['id'],
          name: json['name'],
        );
      }
    }
    

    to :

    class User {
      int? id;
      String? name;
    
      User({this.id, this.name});
    
      User.fromJson(Map<String, dynamic> json) {
        id = json['id'];
        name = json['name'];
      }
    }
    

    and for the view i changed this line :

    from : title: Text(user.name),

    to : title: Text(user.name ?? "it's empty"),

    it worked fine , but i still don't know why exactly , so if anyone could give an explanation i'll be very thankful !