'How to fetch data from the backend with flutter GetX

Please I am trying to fetch data from the backend with flutter GetXService, I am unable to get the data as it keeps telling me that "Null is not a subtype of String". I don't know where am getting it wrong. I follow some youtube videos but still not able to get the response from the server.I used the url on postman and the data is retrieved correctly

Here is my modal class

    class Product {
      int? _totalSize;
      int? _typeId;
      int? _offset;
      late List<ProductsModel> _products;
      List<ProductsModel> get products=>_products;
    
      Product({required totalSize, required typeId, required offset, required products}){
        this._totalSize = totalSize;
        this._typeId = typeId;
        this._offset = offset;
        this._products = products;
      }
    
      Product.fromJson(Map<String, dynamic> json) {
        _totalSize = json['total_size'];
        _typeId = json['type_id'];
        _offset = json['offset'];
        if (json['products'] != null) {
          _products = <ProductsModel>[];
          json['products'].forEach((v) {
            _products!.add(ProductsModel.fromJson(v));
          });
        }
      }
    }
    
    class ProductsModel {
      int? id;
      String? name;
      String? description;
      int? price;
      int? stars;
      String? img;
      String? location;
      String? createdAt;
      String? updatedAt;
      int? typeId;
    
      ProductsModel(
          {this.id,
            this.name,
            this.description,
            this.price,
            this.stars,
            this.img,
            this.location,
            this.createdAt,
            this.updatedAt,
            this.typeId});
    
      ProductsModel.fromJson(Map<String, dynamic> json) {
        id = json['id'];
        name = json['name'];
        description = json['description'];
        price = json['price'];
        stars = json['stars'];
        img = json['img'];
        location = json['location'];
        createdAt = json['created_at'];
        updatedAt = json['updated_at'];
        typeId = json['type_id'];
      }
    }
    

My apiclient class

    import 'package:food_app/utils/app_constants.dart';
    import 'package:get/get.dart';
    
    class ApiClient extends GetConnect implements GetxService{
      late String token;
      final String appBaseUrl;
      late Map<String,String> _mainHeaders;
      ApiClient({required this.appBaseUrl}){
        baseUrl = appBaseUrl;
        timeout=Duration(minutes: 5);
        token = AppConstants.TOKEN;
        _mainHeaders = {
          'Content-type':'application/json; charset=UTF-8',
          'Authorization': 'Bearer $token',
        };
      }
      Future<Response> getData(String uri) async {
        try{
          Response response =await get(uri);
          return response;
        }catch(e){
          print("Error from the api client is "+e.toString());
          return Response(statusCode: 1,statusText: e.toString());
    
        }
      }
    }

My repository

    class PopularProductRepository extends GetxService{
      final ApiClient apiClient;
      PopularProductRepository({required this.apiClient});
    
      Future<Response> getPopularProductList()async{
        return await apiClient.getData(AppConstants.POPULAR_PRODUCTS_URI);
      }
    }

My controller

    class PopularProductController extends GetxController{
      final PopularProductRepository popularProductRepository;
    
    
      PopularProductController({required this.popularProductRepository});
    
    
      List<ProductsModel> _popularProductList=[];
      List<ProductsModel> get popularProductList => _popularProductList;
    
      Future<void> getPopularProductList()async {
        Response response = await popularProductRepository.getPopularProductList();
    
        try{
    
    
        if(response.statusCode==200){
          print("Got products from the server");
          _popularProductList=[];
          _popularProductList.addAll(Product.fromJson(response.body).products);
          print(_popularProductList);
          update();
        }
        else{
          print("Error occurred and the error is "+response.body);
        }
        }catch(e){
          print("Error in the controller is "+e.toString());
        }
      }
    }

init class

    Future <void> init()async {
      //api client
      Get.lazyPut(()=>ApiClient(appBaseUrl: AppConstants.BASE_URL));
    
      //repository
      Get.lazyPut(() => PopularProductRepository(apiClient:Get.find()));
    
      //controller
      Get.lazyPut(() => PopularProductController(popularProductRepository:Get.find()));
    }

Appconstants for my url

    class AppConstants{
    
      static const String APP_NAME = "FoodApp";
      static const int VERSION = 1;
      static const String BASE_URL = "https://mvs.bslmeiyu.com";
      static const String POPULAR_PRODUCTS_URI = "/api/v1/products/popular";
      static const String RECOMMENDED_PRODUCTS_URI = "/api/v1/products/recommended";
      static const String TOKEN = "FoodToken";
    }

Here is the Main page

    import 'package:get/get.dart';
    import 'helper/dependency.dart' as dep;
    import 'home/main_page.dart';
    
    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await dep.init();
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
    
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        Get.find<PopularProductController>().getPopularProductList();
        return GetMaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: const MainPage(),// RecommendedFoodDetails(), //PopularFoodDetails(),//
            debugShowCheckedModeBanner: false,
        );
      }
    }

I got this from the logcat

    [GETX] Instance "PopularProductController" has been created
    [GETX] Instance "PopularProductRepository" has been created
    [GETX] Instance "ApiClient" has been created
    [GETX] Instance "ApiClient" has been initialized
    [GETX] Instance "PopularProductRepository" has been initialized
    [GETX] Instance "PopularProductController" has been initialized
    [GETX] Instance "GetMaterialController" has been created
    [GETX] Instance "GetMaterialController" has been initialized
    [+2855 ms] I/flutter (  548): Error from the api client is type 'Null' is not a subtype of type 'String'
    [   +1 ms] I/flutter (  548): Error in the controller is type 'Null' is not a subtype of type 'String'


Solution 1:[1]

I copied your exact code and it seems to work although I used Text("test") instead of MainPage() because I don't have that one and it seems to work fine for me. Output:

[GETX] Instance "PopularProductController" has been created
[GETX] Instance "PopularProductRepository" has been created
[GETX] Instance "ApiClient" has been created
[GETX] Instance "ApiClient" has been initialized
[GETX] Instance "PopularProductRepository" has been initialized
[GETX] Instance "PopularProductController" has been initialized
[GETX] Instance "GetMaterialController" has been created
[GETX] Instance "GetMaterialController" has been initialized
Got products from the server
[Instance of 'ProductsModel', Instance of 'ProductsModel', Instance of 'ProductsModel', Instance of 'ProductsModel', Instance of 'ProductsModel', Instance of 'ProductsModel']

I have no idea why it doesn't work for you, maybe you can try to upgrade your flutter.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ivo Beckers