1

I have following code in flutter. It is working as expected. I have a services class. It has a getList method. This method returns a List of User.

import 'package:http/http.dart' as http;
const ROOT = 'http://localhost/app/users.php';

class User{
  final String id;
  final String name;
  User({
    this.id,
    this.name,
  });

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

class Services {

Future<List<User>> getList() async {
    try {
      var map = new Map<String, dynamic>();
      map["action"] = "fetch-all";
      final response = await http.post(ROOT, body: map);
      if (response.statusCode == 200) {
        final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
        List<User> list = parsed.map<User>((json) => User.fromJson(json)).toList();
        return list;
      } else {
        throw List<User>();
      }
    } catch (e) {
      return List<User>();
    }
  }

}

I am trying to make a generic method from above code. I can pass any object type (eg: User in this above code) in getList() method as parameter and get the output list this object passed in as parameter.

Eg: Instead of User object is can pass Album Object as parameter and I can get a List of Album as output.

May Be something like this method:

  Future<List> getList({Map map, MyClass}) async {
    final response = await http.post(ROOT, body: map);
    print("getUsers >> Response:: ${response.body}");
    if (response.statusCode == 200) {
      final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
      return parsed.map<MyClass>((json) => User.fromJson(json)).toList();
    } else {
      print("no data");
      throw List<MyClass>();
    }
  }

Here MyClass is a dynamic Object that can be passed.

Jay Babani
  • 103
  • 1
  • 8

2 Answers2

0

Try this:

class Services {

  Future<List<T>> getList<T>() async {
    try {
      var map = new Map<String, dynamic>();
      map["action"] = "fetch-all";
      final response = await http.post(ROOT, body: map);
      if (response.statusCode == 200) {
        final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
        List<T> list = parsed.map<T>((json) => T.fromJson(json)).toList();
        return list;
      } else {
        throw <T>[];
      }
    } catch (e) {
      return <T>[];
    }
  }

}
ng5002
  • 477
  • 2
  • 4
  • 2
    Works but cannot access fromJson method of class T. It gives error: The method fromJson isnt defined for type T. – Jay Babani Jul 22 '20 at 15:47
  • 2
    Error: The method 'fromJson' isn't defined for the class 'Type'. – Jay Babani Jul 22 '20 at 16:00
  • Error: The method 'fromJson' isn't defined for the class 'Type' ``` This line gives error: List list = parsed.map((json) => T.fromJson(json)).toList(); ``` – Jay Babani Jul 22 '20 at 17:07
  • This helped in solving: https://stackoverflow.com/questions/53369276/dart-cant-call-generics-method – Jay Babani Jul 22 '20 at 17:58
0

Solved: Hint Dart, Can't call Generic's method

Passed in fromJson method in constructor of Services class.

Like this below:

class User{
  final String id;
  final String name;
  User({
    this.id,
    this.name,
  });

  factory User.fromJson(Map<String, dynamic> json) {
    return convertMaptoObject(json);
  }

  static toTypeObject(Map<String, dynamic> json) {
    return convertMaptoObject(json);
  }

  static convertMaptoObject(json) {
    return User(
      id: json['id'] as String,
      name: json['name'] as String,
    );
  }
  
}

class Services {
  final Function toTypeObject;
  final String path;
  final String action;

  Services({@required this.toTypeObject, @required this.path, this.action});

  Future<List<T>> getList<T>() async {
    try {
      var map = new Map<String, dynamic>();
      map["action"] = action == null ? 'fetch-all' : action;
      final response = await http.post(RESTAPI + path, body: map);
      print("getUsers >> Response:: ${response.body}");
      if (response.statusCode == 200) {
        print(response.body);
        var parsed = json.decode(response.body).cast<Map<String, dynamic>>();
        print(parsed);
        List<T> list = parsed.map<T>((json) => toTypeObject(json)).toList();
        return list;
      } else {
        throw <T>[];
      }
    } catch (e) {
      return <T>[];
    }
  }
}

Jay Babani
  • 103
  • 1
  • 8