Related
I'm trying to built an app for my college degree with flutter that has a login screen where you insert the username and password and pass to the main screen. I use retrofit for the REST API. When I press the login button with the credentials I get the error: Exception: DioError [DioErrorType.other]: type 'String' is not a subtype of type 'Map<String, dynamic>?' in type cast.
I'm very new in Flutter can you help me? Here is my code:
Api_Service
#RestApi(baseUrl: '...')
abstract class ApiService {
factory ApiService(Dio dio, {required String baseUrl}) {
dio.options = BaseOptions(
receiveTimeout: 3000,
connectTimeout: 3000,
contentType: 'application/json',
headers: <String, String>{
'Authorization': 'Basic Y29hY2g6Y29hY2g=',
'Accept': 'application/json',
},
followRedirects: false,
validateStatus: (status) {
return status! < 400;
});
return _ApiService(dio, baseUrl: baseUrl);
}
//Login Service
#POST('...')
#FormUrlEncoded()
Future<LoginResponse> login(#Body() Map<String, dynamic> body);
Api_Response
#JsonSerializable()
class LoginResponse {
//show login response data
#JsonKey(name: 'Status')
final int statusCode;
#JsonKey(name: 'Message')
final String message;
#JsonKey(name: 'Content')
final UserEntity userEntity;
LoginResponse(this.statusCode, this.message, this.userEntity);
factory LoginResponse.fromJson(Map<String, dynamic> json) =>
_$LoginResponseFromJson(json);
Map<String, dynamic> toJson() => _$LoginResponseToJson(this);
}
User_entity
import 'package:json_annotation/json_annotation.dart';
part 'user_entity.g.dart';
//done this file
#JsonSerializable()
class UserEntity {
#JsonKey(name: 'id')
final String id;
#JsonKey(name: 'username')
final String username;
#JsonKey(name: 'role')
final String role;
UserEntity(this.id, this.username, this.role);
factory UserEntity.fromJson(Map<String, dynamic> json) =>
_$UserEntityFromJson(json);
Map<String, dynamic> toJson() => _$UserEntityToJson(this);
}
User
class User {
String? id;
String? username;
String? role;
String? token;
String? renewalToken;
User({this.id, this.username, this.role, this.token, this.renewalToken});
factory User.fromJson(Map<String, dynamic> responseData) {
return User(
id: responseData['id'],
username: responseData['username'],
role: responseData['role'],
token: responseData['token'],
renewalToken: responseData['token'],
);
}
User_provider
class UserProvider extends ChangeNotifier {
User _user = User();
User get user => _user;
void setUser(User? user) {
_user = user!;
notifyListeners();
}
}
Auth_provider
enum Status { NotLoggedIn, LoggedIn, Authenticating, LoggedOut }
class AuthProvider extends ChangeNotifier {
Status _loggedInStatus = Status.NotLoggedIn;
Status get loggedInStatus => _loggedInStatus;
set loggedInStatus(Status value) {
_loggedInStatus = value;
}
static Future<FutureOr> onValue(Response response) async {
var result;
final Map<String, dynamic> responseData = json.decode(response.body);
print(responseData);
if (response.statusCode == 200) {
// now we will create a user model
User authUser = User.fromJson(responseData);
// now we will create shared preferences and save data
UserPreferences().saveUser(authUser);
result = {
'status': true,
'message': 'Successfully registered',
'data': authUser
};
} else {
result = {
'status': false,
'message': 'Successfully registered',
'data': responseData
};
}
return result;
}
Future<Map<String, dynamic>> login(String username, String password) async {
var result;
Map<String, dynamic> loginData = {
'Username': username,
'Password': password,
};
_loggedInStatus = Status.Authenticating;
notifyListeners();
ApiService apiService = ApiService(dio.Dio(), baseUrl: '');
final response = await apiService.login(loginData);
print('${response.toJson()}');
if (response.statusCode == 200) {
User authUser = User(
id: response.userEntity.id,
username: response.userEntity.username,
role: response.userEntity.role,
);
UserPreferences().saveUser(authUser);
_loggedInStatus = Status.LoggedIn;
notifyListeners();
result = {'status': true, 'message': 'Successful', 'user': authUser};
} else {
_loggedInStatus = Status.NotLoggedIn;
notifyListeners();
result = {'status': false, 'message': ''};
}
return result;
}
onError(error) {
print('the error is ${error.detail}');
return {'status': false, 'message': 'Unsuccessful Request', 'data': error};
}
}
Main
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
Future<User> getUserData() => UserPreferences().getUser();
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => AuthProvider()),
ChangeNotifierProvider(create: (_) => UserProvider())
],
child: MaterialApp(
theme: ThemeData(
backgroundColor: Color(0Xfff7f7f5),
fontFamily: 'Cera',
appBarTheme: AppBarTheme(
backgroundColor: Colors.white,
),
),
debugShowCheckedModeBanner: false,
// home: LoginScreen(),
home: FutureBuilder<User>(
future: getUserData(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return CircularProgressIndicator();
default:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
else if (snapshot.data!.token == null) {
return LoginScreen();
} else
Provider.of<UserProvider>(context).setUser(snapshot.data);
return TeamsScreen();
}
}),
routes: {
'/auth': (context) => LoginScreen(),
'/teams': (context) => TeamsScreen(),
},
));
}
}
shared_preferences
class UserPreferences {
Future<bool> saveUser(User user) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('id', user.id as String);
prefs.setString('username', user.username as String);
prefs.setString('role', user.role as String);
prefs.setString('token', user.token as String);
return saveUser(user);
}
Future<User> getUser() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
String id = prefs.getString("id") ?? '';
String username = prefs.getString("username") ?? '';
String role = prefs.getString("role") ?? '';
String token = prefs.getString("token") ?? '';
String renewalToken = prefs.getString("renewalToken") ?? '';
return User(
id: id,
username: username,
role: role,
token: token,
renewalToken: renewalToken);
}
void removeUser() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.remove('id');
prefs.remove('username');
prefs.remove('role');
prefs.remove('token');
}
Future<String?> getToken() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString("token");
return token;
}
}
That's because the server is returning a json string with a different encoding than application/json. Check your response headers and you should probably see that the Content-Type of your response is not application/json but something else. I had the error when getting a GitLab snippet that was not returned as actual json but as a string.
You have two solutions here :
Ask your server for application/json Content-Type, and if he's a nice server he will comply to your request and return proper json. You can do that by setting HTTP headers either in Dio global options or for a specific request.
In your case it seems you already have tried this option but the server didn't want to comply to your request, so you should probably try option 2.
Add a Dio interceptor that will do the conversion from a String to a Map<dynamic, String> before it's actually treated by Retrofit generated code :
final dio = Dio()
..interceptors.add(
InterceptorsWrapper(
onResponse: (response, handler) {
if (response.requestOptions.method == HttpMethod.GET) {
response.data = jsonDecode(response.data as String);
}
return handler.next(response);
},
),
);
I am using an API,to fetch data and display it in a list view after some constraints.I am fetching the data from the API ,it is printing as well and getting stored as well.But still I am getting Unhandled Exception: DatabaseException(datatype mismatch),though I checked the order in which I have put them down in correct.I am really fed up with this JSON parsing.It is a real pain actually speaking.
Below is the list of dart files I have used in my flutter project:
This is my main file,where I will be displaying the data in a list view:
import 'package:flutter/material.dart';
import 'services.dart';
import 'db_provider.dart';
void main() => runApp(Main());
class Main extends StatefulWidget {
#override
_MainState createState() => _MainState();
}
class _MainState extends State<Main> {
var isLoading = false;
_loadFromApi() async {
setState(() {
isLoading = true;
});
var apiProvider = Services();
await apiProvider.getAllCustomers();
// wait for 2 seconds to simulate loading of data
await Future.delayed(const Duration(seconds: 2));
setState(() {
isLoading = false;
});
}
Widget _buildEmployeeListView() {
return FutureBuilder(
future: DBProvider.db.getAllCustomers(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
} else {
return ListView.separated(
separatorBuilder: (context, index) =>
Divider(
color: Colors.black12,
),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: Text(
"${index + 1}",
style: TextStyle(fontSize: 20.0),
),
title: Text(
"Name: ${snapshot.data[index].name} "),
subtitle: Text('status: ${snapshot.data[index].status}'),
);
},
);
}
},
);
}
#override
void initState() {
super.initState();
_loadFromApi();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Customer details'),
),
body: _buildEmployeeListView(),
),
);
}
}
Below is my JSON data:
{
"list":[
{
"id":"MnJJA0dbuw",
"name":"Anand Sharma",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Anand.jpeg",
"gender":"m",
"age":46,
"date":"23/11/2019",
"status":"onboarded"
},
{
"id":"MnZmmmbuw",
"name":"Malashri Lal",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Vishesh.jpg",
"gender":"f",
"age":70,
"date":"01/10/2019",
"status":"active"
},
{
"id":"MnZy10dpsq",
"name":"Suhasini Haidar",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Suhasini.jpg",
"gender":"f",
"age":30,
"date":"23/03/2019",
"status":"left"
},
{
"id":"HOnmFt5jA",
"name":"Vishesh Mahajan",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Vishesh.jpg",
"gender":"m",
"age":34,
"date":"05/05/2019",
"status":"active"
},
{
"id":"MnZy10dxyz",
"name":"Anand Neelakantan",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Anand.jpeg",
"gender":"m",
"age":46,
"date":"03/10/2019",
"status":"left"
},
{
"id":"MnZy1JJbuw",
"name":"Malashri",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Malashri.jpg",
"gender":"f",
"age":65,
"date":"04/01/2019",
"status":"active"
},
{
"id":"JKAS10dbuw",
"name":"Meenakshi Madhavan",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Meenakshi.jpg",
"gender":"f",
"age":35,
"date":"01/03/2020",
"status":"left"
},
{
"id":"sOw8c6BOug",
"name":"Fintan",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Fintan.jpg",
"gender":"m",
"age":55,
"date":"09/12/2019",
"status":"onboarded"
},
{
"id":"MnZy10dlll",
"name":"Jaishree Periwal",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Jaishree.jpg",
"gender":"f",
"age":50,
"date":"01/02/2020",
"status":"active"
},
{
"id":"KbN3VELflA",
"name":"Anukriti Upadhyay",
"img":"https://incablet-tests.s3.ap-south-1.amazonaws.com/conference-content/photos/sponsors/Anukriti.jpg",
"gender":"f",
"age":30,
"date":"31/01/2020",
"status":"onboarded"
}
]
}
Below is the PODO file I have created:
// To parse this JSON data, do
//
// final customerInfo = customerInfoFromJson(jsonString);
import 'dart:convert';
CustomerInfo customerInfoFromJson(String str) => CustomerInfo.fromJson(json.decode(str));
String customerInfoToJson(CustomerInfo data) => json.encode(data.toJson());
class CustomerInfo {
CustomerInfo({
this.list,
});
List<ListElement> list;
factory CustomerInfo.fromJson(Map<String, dynamic> json) => CustomerInfo(
list: List<ListElement>.from(json["list"].map((x) => ListElement.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"list": List<dynamic>.from(list.map((x) => x.toJson())),
};
}
class ListElement {
ListElement({
this.id,
this.name,
this.img,
this.gender,
this.age,
this.date,
this.status,
});
String id;
String name;
String img;
Gender gender;
int age;
String date;
Status status;
factory ListElement.fromJson(Map<String, dynamic> json) => ListElement(
id: json["id"],
name: json["name"],
img: json["img"],
gender: genderValues.map[json["gender"]],
age: json["age"],
date: json["date"],
status: statusValues.map[json["status"]],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"img": img,
"gender": genderValues.reverse[gender],
"age": age,
"date": date,
"status": statusValues.reverse[status],
};
}
enum Gender { M, F }
final genderValues = EnumValues({
"f": Gender.F,
"m": Gender.M
});
enum Status { ONBOARDED, ACTIVE, LEFT }
final statusValues = EnumValues({
"active": Status.ACTIVE,
"left": Status.LEFT,
"onboarded": Status.ONBOARDED
});
class EnumValues<T> {
Map<String, T> map;
Map<T, String> reverseMap;
EnumValues(this.map);
Map<T, String> get reverse {
if (reverseMap == null) {
reverseMap = map.map((k, v) => new MapEntry(v, k));
}
return reverseMap;
}
}
Below is the db provider I have created to store the data.I need to still write the SQL command to properly get the data in the required sorting order.For the time being it is Select *
import 'dart:io';
import 'podo_file.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
//9-22 creating a Database object and instantiating it if not initialized.
class DBProvider {
static Database _database;
static final DBProvider db = DBProvider._();
DBProvider._();
Future<Database> get database async {
// If database exists, return database
if (_database != null) return _database;
// If database don't exists, create one
_database = await initDB();
return _database;
}
initDB() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
final path = join(documentsDirectory.path, 'Customer_Info.db');
return await openDatabase(path, version: 1, onOpen: (db) {},
onCreate: (Database db, int version) async {
await db.execute('CREATE TABLE CUSTOMER_DATA('
'id TEXT PRIMARY KEY,'
'name TEXT,'
'img TEXT,'
'gender TEXT'
'age INTEGER,'
'date TEXT,'
'status TEXT,'
')');
});
}
// Insert employee on database
createCustomer(ListElement newCustomer) async {
await deleteAllCustomers();
final db = await database;
final res = await db.insert('CUSTOMER_DATA', newCustomer.toJson());
return res;
}
// Delete all employees
Future<int> deleteAllCustomers() async {
final db = await database;
final res = await db.rawDelete('DELETE FROM CUSTOMER_DATA');
return res;
}
Future<List<ListElement>> getAllCustomers() async {
final db = await database;
final res = await db.rawQuery("SELECT * FROM CUSTOMER_DATA");
List<ListElement> list =
res.isNotEmpty ? res.map((c) => CustomerInfo.fromJson(c)).toList() : [];
return list;
}
}
Below is the service file I have created which will get the data:
import 'dart:convert';
import 'package:flutter/animation.dart';
import 'package:flutterappincablet/podo_file.dart';
import 'package:http/http.dart' as http;
import 'db_provider.dart';
class Services {
Future<List<ListElement>> getAllCustomers() async {
var url = "https://5w05g4ddb1.execute-api.ap-south-1.amazonaws.com/dev/profile/listAll";
final response = await http.get(url);
Map<String, dynamic> map = json.decode(response.body);
print('nnnnnnnnnn');
print(map);
List<dynamic> data = map["list"];
print('xxxxxxxxxxxxxxxxx');
print(data);
return (data as List).map((c) {
print('Inserting $c');
DBProvider.db.createCustomer(ListElement.fromJson(c));
}).toList();
}
}
Below is the screenshot of the error:
I use this topology model to parse Json data. The data become garbled when I receive Chinese characters.
I have tried to add utf8.decode like
List<Client> clientFromJson(String str) => List<Client>.from(json.decode(utf8.decode(str)).map((x) => Client.fromJson(x)));
but the IDE tell me that "The argument type 'String' can't be assigned to the parameter type 'List< int >' ".
What should I do to add utf8 decoder in the model?
///topology.dart
// To parse this JSON data, do
//
// final client = clientFromJson(jsonString);
// final topology = topologyFromJson(jsonString);
import 'dart:convert';
List<Client> clientFromJson(String str) => List<Client>.from(json.decode(str).map((x) => Client.fromJson(x)));
String clientToJson(List<Client> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
List<Topology> topologyFromJson(String str) => List<Topology>.from(json.decode(str).map((x) => Topology.fromJson(x)));
String topologyToJson(List<Topology> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Topology {
String location;
String mode;
String macAddress;
String ipAddress;
String downloadSpeed;
String downloadSpeedUnit;
String uploadSpeed;
String uploadSpeedUnit;
List<Client> client;
Topology({
this.location,
this.mode,
this.macAddress,
this.ipAddress,
this.downloadSpeed,
this.downloadSpeedUnit,
this.uploadSpeed,
this.uploadSpeedUnit,
this.client,
});
factory Topology.fromJson(Map<String, dynamic> json) => Topology(
location: json["location"],
mode: json["mode"],
macAddress: json["macAddress"],
ipAddress: json["ipAddress"],
downloadSpeed: json["downloadSpeed"],
downloadSpeedUnit: json["downloadSpeedUnit"],
uploadSpeed: json["uploadSpeed"],
uploadSpeedUnit: json["uploadSpeedUnit"],
client: List<Client>.from(json["client"].map((x) => Client.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"location": location,
"mode": mode,
"macAddress": macAddress,
"ipAddress": ipAddress,
"downloadSpeed": downloadSpeed,
"downloadSpeedUnit": downloadSpeedUnit,
"uploadSpeed": uploadSpeed,
"uploadSpeedUnit": uploadSpeedUnit,
"client": List<dynamic>.from(client.map((x) => x.toJson())),
};
}
class Client {
String hostname;
String macAddress;
String ipAddress;
String deviceType;
String connectedNebula;
String connectionType;
String connectTime;
Client({
this.hostname,
this.macAddress,
this.ipAddress,
this.deviceType,
this.connectedNebula,
this.connectionType,
this.connectTime,
});
factory Client.fromJson(Map<String, dynamic> json) => Client(
hostname: json["hostname"],
macAddress: json["macAddress"],
ipAddress: json["ipAddress"],
deviceType: json["deviceType"],
connectedNebula: json["connectedNebula"],
connectionType: json["connectionType"],
connectTime: json["connectTime"],
);
Map<String, dynamic> toJson() => {
"hostname": hostname,
"macAddress": macAddress,
"ipAddress": ipAddress,
"deviceType": deviceType,
"connectedNebula": connectedNebula,
"connectionType": connectionType,
"connectTime": connectTime,
};
}
//main.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Topology',
theme: ThemeData(),
home: Home(),
);
}
}
class Home extends StatefulWidget {
final String title;
const Home({Key key, this.title}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
var topologies = const [];
Future loadTopologyList() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String managementPassword = prefs.getString("management_password");
String username = 'admin';
String basicAuth =
'Basic ' + base64Encode(utf8.encode('$username:$managementPassword'));
final String url ="some url";
bool trustSelfSigned = true;
HttpClient httpClient = HttpClient()
..badCertificateCallback =
((X509Certificate cert, String host, int port) => trustSelfSigned);
IOClient ioClient = IOClient(httpClient);
final response = await ioClient.get(url,
headers: <String, String>{'authorization': basicAuth},
);
ioClient.close();
String content = response.body;
setState(() {
topologies = topologyFromJson(content);
});
}
void initState() {
loadTopologyList();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFFAFAFA),
appBar: AppBar(),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(17, 0, 0, 0),
child: Text('Topology'),
),
Expanded(
child: ListView.separated(
itemCount: topologies.length,
separatorBuilder: (context, index) => Divider(),
itemBuilder: (BuildContext context, int index) {
Topology topology = topologies[index];
return ListTile(
title: Text(
topology.location,
),
leading: CircleAvatar(
child: Image.asset(
"assets/drawable-mdpi/app_icon_circle.png")),
onTap: () {
},
);
},
),
),
],
),
);
}
}
You have to pass the response.bodyBytes when using utf8.decode.
For example:
json.decode(utf8.decode(response.bodyBytes))
and If you got a String then you can use below code to decode.
utf8.decode(someString.runes.toList()),
I got this error:
Unhandled Exception: type 'List' is not a subtype of type 'String'
I got this error when I modify the topology.dart
List<Client> clientFromJson(String str) => List<Client>.from(json.decode(utf8.decode(str.runes.toList())).map((x) => Client.fromJson(x)));
String clientToJson(List<Client> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
List<Topology> topologyFromJson(String str) => List<Topology>.from(json.decode(utf8.decode(str.runes.toList())).map((x) => Topology.fromJson(x)));
String topologyToJson(List<Topology> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
and in the main.dart
final json = jsonDecode(utf8.decode(response.bodyBytes));
setState(() {
topologies = topologyFromJson(json);
});
its actually continuation of my previous question, here i've been successfully populate my list with Json which i retrieved from Get method. as the suggestion, i used futurebuilder widget to build my Dropdownbutton. but my problem is: it cant display any after i picked up the dropdownlist. it crashes.
and i had other thing concerned me. my project is to receive scanned nearby wifi by an esp8266 through http GET method (and later send the password through the apps using POST method). my question is:
when im using this Futurebuilder widget, in which "time" that this app actually made http request? does it refresh all the time?
can i just populate the dropdownmenuitem in just one occasion (perhaps in initstate), then asking for refresh only when i needed it (i.e using a button). i've been trying to do this but it kept failing.
here's my code
Future<List<Post>> getAllPosts(String url) async {
final response = await http.get(url);
return allPostsFromJson(response.body);
}
List<Post> allPostsFromJson(String str) {
final jsonData = json.decode(str);
return new List<Post>.from(jsonData.map((x) => Post.fromJson(x)));
}
class Post {
String name;
String perc;
String pass;
Post({
this.name,
this.perc,
this.pass,
});
factory Post.fromJson(Map<String, dynamic> json) => new Post(
name: json["SSID"],
perc: json["RSSI"],
pass: json["PASS"],
);
Map<String, dynamic> toJson() => {
"SSID": name,
"RSSI": perc,
"PASS": pass,
};
}
class LoginPhaseState extends State<LoginPhase>{
Post selected;
final String uri = 'http://10.0.2.2/data/connection.json';
#override
Widget build(BuildContext context) {
return FutureBuilder<List<Post>>(
future: getAllPosts(uri),
builder: (BuildContext context,
AsyncSnapshot<List<Post>> snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
return DropdownButton<Post>(
items: snapshot.data
.map((ssid) => DropdownMenuItem<Post>(
child: Text(ssid.name),
value: ssid,
))
.toList(),
onChanged: (Post value) {
setState(() {
selected = value;
});
},
isExpanded: false,
// value: selected,
hint: Text('Select User'),
);
});
}
}
try this,
Future<List<Post>> getAllPosts(String url) async {
final response = await http.get(url);
return allPostsFromJson(response.body);
}
List<Post> allPostsFromJson(String str) {
final jsonData = json.decode(str);
return new List<Post>.from(jsonData.map((x) => Post.fromJson(x)));
}
class Post {
String name;
String perc;
String pass;
Post({
this.name,
this.perc,
this.pass,
});
factory Post.fromJson(Map<String, dynamic> json) => new Post(
name: json["SSID"],
perc: json["RSSI"],
pass: json["PASS"],
);
Map<String, dynamic> toJson() => {
"SSID": name,
"RSSI": perc,
"PASS": pass,
};
}
class LoginPhaseState extends State<LoginPhase>{
Post selected;
final String uri = 'http://10.0.2.2/data/connection.json';
String _selectedChild= "";
#override
Widget build(BuildContext context) {
return FutureBuilder<List<Post>>(
future: getAllPosts(uri),
builder: (BuildContext context,
AsyncSnapshot<List<Post>> snapshot) {
if (!snapshot.hasData)
return CircularProgressIndicator();
return DropdownButton<Post>(
value: _selectedChild == "" ? null : _selectedChild,
items: snapshot.data
.map((ssid) => DropdownMenuItem<Post>(
child: Text(ssid.name),
value: ssid,
))
.toList(),
onChanged: (Post value) {
setState(() {
_selectedChild = value.name;
selected = value;
});
},
isExpanded: false,
// value: selected,
hint: Text('Select User'),
);
});
}
}
i try to fetch api json id , username , photo ..etc...
and when use jsonplaceholder it's working fine
and when use mine don't get any data
flutter code
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class ListViewJsonapi extends StatefulWidget {
_ListViewJsonapiState createState() => _ListViewJsonapiState();
}
class _ListViewJsonapiState extends State<ListViewJsonapi> {
final String uri = 'https://www.christian-dogma.com/android-index.php';
Future<List<Users>> _fetchUsers() async {
var response = await http.get(uri);
if (response.statusCode == 200) {
final items = json
.decode(utf8.decode(response.bodyBytes))
.cast<Map<String, dynamic>>();
List<Users> listOfUsers = items.map<Users>((json) {
return Users.fromJson(json);
}).toList();
return listOfUsers;
} else {
throw Exception('Failed to load internet');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<Users>>(
future: _fetchUsers(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(child: CircularProgressIndicator());
return ListView(
children: snapshot.data
.map((user) => ListTile(
title: Text(user.name),
subtitle: Text(user.email),
leading: CircleAvatar(
backgroundColor: Colors.red,
child: Text(user.name[0],
style: TextStyle(
fontSize: 18.0,
color: Colors.white,
)),
),
))
.toList(),
);
},
),
);
}
}
class Users {
int id;
String name;
String username;
String email;
Users({
this.id,
this.name,
this.username,
this.email,
});
factory Users.fromJson(Map<String, dynamic> json) {
return Users(
id: json['id'],
name: json['name'],
email: json['email'],
username: json['username'],
);
}
}
when use https://jsonplaceholder.typicode.com/users it's working fine
and when use mine https://www.christian-dogma.com/android-index.php i don't get any data
He managed to make it work, one of the problems he has is that the id asks me to be a String since you had it as an integer, I hope it worked for you.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class JsonApiPhp extends StatefulWidget {
#override
_JsonApiPhpState createState() => _JsonApiPhpState();
}
class _JsonApiPhpState extends State<JsonApiPhp> {
bool loading = true;
final String url = 'https://www.christian-dogma.com/android-index.php';
var client = http.Client();
List<User> users = List<User>();
#override
void initState(){
fetchData();
super.initState();
}
Future<void> fetchData() async {
http.Response response = await client.get(url);
if(response.statusCode == 200){ // Connection Ok
List responseJson = json.decode(response.body);
responseJson.map((m) => users.add(new User.fromJson(m))).toList();
setState(() {
loading = false;
});
} else {
throw('error');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: loading ?
Container(
child: Center(
child: CircularProgressIndicator(),
),
) :
ListView.builder(
itemCount: users.length,
itemBuilder: (BuildContext context, int index){
return Card(
child: ListTile(
title: Text(users[index].username),
),
);
},
)
),
);
}
}
class User {
final String id;
final String name;
final String username;
final String email;
User({
this.id,
this.name,
this.username,
this.email,
});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
email: json['email'],
username: json['username'],
);
}
}
I kind of banged my head around and finally found out that your JSON response is returning the id as a string and not as an integer.
Change the factory to following code.
factory Users.fromJson(Map<String, dynamic> json) {
return Users(
id: int.parse(json['id']),
name: json['name'],
email: json['email'],
username: json['username'],
);
Cheers!