I have a method of type Future when I call other methods in this method it does not recognize them.
Here is my code:
static Future<void> createUser(String email, String password, String role,
{GlobalKey<ScaffoldState> scaffoldKey}) async {
RestClient.getAuthToken().then((String token) {
Map<String, dynamic> postData = {
"email": email,
"password": password,
"role": role
};
RestClient.procesPostRequest("user/add", postData, token)
.then((Map<String, dynamic> data) {
//String message;
if (data.containsKey('error')) {
// print('Error Data : $data');
// message = WSErrorHandler.fromJson(data).getMessage();
isNotRegisteredState();
//return Future.value(message);
} else {
isRegisteredState();
}
});
}).catchError((onError) {
print('$onError');
return Future.value('error');
});
}
These are the methods I call inside the future method:
void isRegisteredState() {
_isRegistered = true;
notifyListeners();
}
void isNotRegisteredState() {
_isRegistered = false;
notifyListeners();
}
And this is the error I get when I run the program:
Error: Method not found: 'isNotRegisteredState', Error: Method not found: 'isRegisteredState'
Related
I'm using the implementation 'com.android.volley:volley:1.1.1' to make a POST call to a REST web service. Unfortunately, the conclusion (i.e. User does not exist) is reached before the response comes back from the server and is always wrong (In reality user actually does exist).
On the console, the logger messages appear in the wrong order:
E/: THIS IS SUPPOSED TO HAPPEN SECOND - USER NOT FOUND ALERT
I/: THIS IS SUPPOSED TO HAPPEN FIRST: VALIDATING DATA
After hours of reading, I found that a Callback Interface will ensure proper execution order. However, after implementing it, the result is the same. What could be wrong, please?
ControladorLoginExistente.Java
public class ControladorLoginUsrExistente {
public AbstractMap.SimpleEntry<String, Map<String, String>> callEndpointLoginUsrExistente(Context context) {
try {
JSONObject jsonRequest = new JSONObject();
jsonRequest.put("email", "mymail#themail.com");
jsonRequest.put("password", "12345");
final JSONObject[] jsonResponse = {null};
new PostRequestConVolley().getResponse(Constantes.URL_ACCESO_USUARIO_EXISTENTE, jsonRequest, context, new VolleyCallback() {
#Override
public void onSuccessResponse(JSONObject jsonObject) {
jsonResponse[0] = jsonObject;
Log.i(null,"THIS IS SUPPOSED TO HAPPEN FIRST: VALIDATING DATA");
}
});
Boolean exito = jsonResponse[0].getBoolean("exito");
String descripcion = jsonResponse[0].getString("descripcion");
String codigoHttp = jsonResponse[0].getString("codigoHttp");
JSONArray respuestaTransaccion = jsonResponse[0].getJSONArray("respuestaTransaccion");
if(exito == false || codigoHttp.equals("200")){
Log.e(null,"THIS IS SUPPOSED TO HAPPEN SECOND: USER NOT FOUND ALERT");
return new AbstractMap.SimpleEntry<>(descripcion, new HashMap<>());
}
Log.i(null,"THIS IS SUPPOSED TO HAPPEN SECOND: USER NOT FOUND ALERT");
return new AbstractMap.SimpleEntry<>(Constantes.EXITO, new HashMap<>());
} catch (Exception ex) {
Log.e(null,"THIS IS SUPPOSED TO HAPPEN SECOND: USER NOT FOUND ALERT");
return new AbstractMap.SimpleEntry<>("ERROR: " + ex.toString(), new HashMap<>());
}
}
}
PostRequestConVolley.java
public class PostRequestConVolley {
public JSONObject getResponse(String url, JSONObject body, Context context, final VolleyCallback callback) {
try {
RequestQueue queue = Volley.newRequestQueue(context);
JsonObjectRequest jsonRequest = new JsonObjectRequest(POST, url, body,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
callback.onSuccessResponse(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(null, error.toString());
}
}) {
#Override
public Map<String, String> getHeaders() {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/json");
params.put("Connection", "keep-alive");
return params;
}
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
Log.i(null, "El HTTP code es:" + response.statusCode);
return super.parseNetworkResponse(response);
}
};
queue.add(jsonRequest);
} catch (Exception ex) {
ex.printStackTrace();
}
return body;
}
}
VolleyCallbackInterface
import org.json.JSONObject;
public interface VolleyCallback {
void onSuccessResponse(JSONObject jsonObject);
}
I want to fetch data from the server, then parse json. When they are done, I want to navigate to another view.
void getServerData() async{
WebRequests ws = WebRequests('https://sampleurl');
Map<String, dynamic> map = await ws.getData();
mychamplist = map['mychampionships'];
mychamplist.forEach((f){
mychampionships.add(MyChampionships(
name: f['name'],
id: int.parse(f['id']),
numberOfPlayers: int.parse(f['nofplayers']),
));
});
Navigator
.of(context)
.pushReplacement(new MaterialPageRoute(builder: (BuildContext context) {
return FantasyNbi();
}));
}
It navigates to the FantasyNbi class before the previous code finished.
How could it do in proper way?
I do have a example class for you that you could use:
class API {
static Future getData(String url) {
return http.get('api link' + url);
}
static Future<List<BasicDiskInfo>> fetchAllDisks() async {
final response = await getData('disk');
if (response.statusCode == 200) {
Iterable list = json.decode(response.body);
List<BasicDiskInfo> disks =
list.map((model) => BasicDiskInfo.fromJson(model)).toList();
return disks;
} else {
throw Exception('Failed to load disks');
}
}
static Future<Disk> fetchDisk(int id) async {
final response = await getData('disk/' + id.toString());
if (response.statusCode == 200) {
return Disk.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load disk');
}
}
}
class Disk {
int id;
String name;
String volumeLable;
bool isReady;
String driveType;
String driveFormat;
int totalSize;
int totalFreeSpace;
int availableFreeSpace;
Disk(
{this.id,
this.name,
this.volumeLable,
this.isReady,
this.driveType,
this.driveFormat,
this.totalSize,
this.totalFreeSpace,
this.availableFreeSpace});
factory Disk.fromJson(Map<String, dynamic> json) {
return Disk(
id: json['id'],
name: json['name'],
volumeLable: json['volumeLable'],
isReady: json['isReady'],
driveType: json['driveType'],
driveFormat: json['driveFormat'],
totalSize: json['totalSize'],
totalFreeSpace: json['totalFreeSpace'],
availableFreeSpace: json['availableFreeSpace']);
}
}
And to get the data I can do this:
var data = await API.fetchAllDisks();
// or
API.fetchAllDisks().then((response) => {/* do something */})
I am creating login view in flutter.I created utility class to handle all the api calling.On Tap am able to make the Api call and also getting the response
successfully.Now the problem is i want to send the response to the main class so that i can parse the data.
Utility.dart:
Future<dynamic> postRequest(String methodName, var body) async{
return await http
.post(Uri.encodeFull(BASE_URL + methodName), body: body, headers: {"Accept":"application/json"})
.then((http.Response response) {
print(response.body);
final int statusCode = response.statusCode;
print("Response obj: ${response.body}");
return response.body;
});
LoginClass.dart:
void _validateInputs() {
if (_email.isNotEmpty && _passWord.isNotEmpty) {
if(_connectionStatus!="ConnectivityResult.none"){
setState(() {
var stringParams = {"Email": _email, "Password": _passWord};
Future<User> response = Utility().postRequest(
"Account/login", stringParams);
if(reponse.statusCode==200){
// Push view to home screen
}
});
}else{
Utility.showAlertPopup(context, "No Internet", "Please check internet connectivity");
}
}
}
class User {
final int UserID;
final int UserName;
User({this.UserID, this.UserName});
factory User.fromJson(Map<String, dynamic> json) {
return User(
UserID: json['userID'],
UserName: json['UserName'],
);
}
M not getting the response back to the login class. What will be the best way to achieve the result.
you should use await in order to wait for the response to return, so your _validateInputs() method should be as follows, and you need to add the setState after you get the response:
void _validateInputs() async{
if (_email.isNotEmpty && _passWord.isNotEmpty) {
if(_connectionStatus!="ConnectivityResult.none"){
var stringParams = {"Email": _email, "Password": _passWord};
Future<User> response = await Utility().postRequest(
"Account/login", stringParams);
setState((){
//add your setState code here, for example remove the loader or something like that
});
if(reponse.statusCode==200){
// Push view to home screen
}
}else{
Utility.showAlertPopup(context, "No Internet", "Please check internet connectivity");
}
}
}
I am trying to fetch some data from network and store it in sqlite database. Following is the model class
class StudentModel {
int status;
String msg;
StudentModelData studentModelData;
StudentModel({this.status, this.msg, this.studentModelData});
StudentModel.fromJson(Map<String, dynamic> json) {
status = json['status'];
msg = json['msg'];
studentModelData = json['data'] != null ? new StudentModelData.fromJson(json['data']) : null;
}
StudentModel.fromDb(Map<String, dynamic> parsedJson) {
status = parsedJson['status'];
msg = parsedJson['msg'];
studentModelData = studentModelData = jsonDecode(json['data']) != null ? new StudentModelData.fromJson(jsonDecode(json['data'])) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
data['msg'] = this.msg;
if (this.studentModelData != null) {
data['data'] = this.studentModelData.toJson();
}
return data;
}
}
class StudentModelData {
int lastIndex;
List<StudentData> studentData;
StudentModelData({this.lastIndex, this.studentData});
StudentModelData.fromJson(Map<String, dynamic> json) {
lastIndex = json['lastIndex'];
if (json['studentData'] != null) {
studentData = new List<StudentData>();
json['studentData'].forEach((v) {
studentData.add(new StudentData.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['lastIndex'] = this.lastIndex;
if (this.studentData != null) {
data['studentData'] = this.studentData.map((v) => v.toJson()).toList();
}
return data;
}
}
class StudentData {
String studentId;
String studName;
String studProfilepic;
String studentEmail;
String studentMobile;
String courseName;
String classCode;
int minAvg;
int avg;
StudentData(
{this.studentId,
this.studName,
this.studProfilepic,
this.studentEmail,
this.studentMobile,
this.courseName,
this.classCode,
this.minAvg,
this.avg});
StudentData.fromJson(Map<String, dynamic> json) {
studentId = json['student_id'];
studName = json['stud_name'];
studProfilepic = json['stud_profilepic'];
studentEmail = json['student_email'];
studentMobile = json['student_mobile'];
courseName = json['course_name'];
classCode = json['class_code'];
minAvg = json['minAvg'];
avg = json['avg'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['student_id'] = this.studentId;
data['stud_name'] = this.studName;
data['stud_profilepic'] = this.studProfilepic;
data['student_email'] = this.studentEmail;
data['student_mobile'] = this.studentMobile;
data['course_name'] = this.courseName;
data['class_code'] = this.classCode;
data['minAvg'] = this.minAvg;
data['avg'] = this.avg;
return data;
}
}
And my database provider class looks like following
class StudentDbProvider implements Source, Cache {
Database db;
StudentDbProvider() {
init();
}
void init() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
final path = join(documentsDirectory.path, "students.db");
db = await openDatabase(path, version: 1,
onCreate: (Database newDb, int version) {
newDb.execute("""
CREATE TABLE STUDENTS(
id INTEGER PRIMARY KEY,
status INTEGER,
msg TEXT,
data BLOB
)
""");
});
}
#override
Future<int> clear() {
return db.delete("STUDENTS");
}
#override
Future<StudentModel> fetchStudents(String disciplineId, String schoolId,
String year_id, String lastIndex) async {
final maps =
await db.query("STUDENTS");
if (maps.length > 0) {
return StudentModel.fromDb(maps.first);
}
return null;
}
#override
Future<int> addStudent(StudentModel studentModel) {
return db.insert("STUDENTS", studentModel.toJson(),conflictAlgorithm: ConflictAlgorithm.ignore);
}
}
final studentDbProvider = StudentDbProvider();
Whenever I tried to fetch the data and stored in the database, I get the following error in the console
NoSuchMethodError: The method 'query' was called on null.
Receiver: null
Tried calling: query("STUDENTS")
#0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
The data gets added to the database but I am not able to query the data from the database.
Reducing at minimum your example, this throws the exception The method 'query' was called on null
because fetch is executed before db is properly initialized:
class Database {
Future<int> query() {
return Future.value(1);
}
}
const oneSecond = Duration(seconds: 1);
class Provider {
Database db;
Provider() {
init();
}
void init() async {
db = await Future.delayed(oneSecond, () => Database());
}
Future<int> fetch() {
return db.query();
}
}
main() async {
var provider = Provider();
await provider.fetch();
}
The problem resides in calling an async method inside a constructor, see also:
Calling an async method from component constructor in Dart
This works:
class Database {
Future<int> query() {
return Future.value(1);
}
}
const oneSecond = Duration(seconds: 1);
class Provider {
Database db;
Provider() {
//init();
}
void init() async {
db = await Future.delayed(oneSecond, () => Database());
}
Future<int> fetch() {
return db.query();
}
}
main() async {
var provider = Provider();
await provider.init();
await provider.fetch();
}
Please note that init must be awaited, otherwise you will catch the same The method 'query' was called on null.
the problem is the init must be awaited. here what I did to fix it
_onCreate(Database db, int version) async {
await db.execute('CREATE TABLE ... <YOUR QUERY CREATION GOES HERE>');
}
Future<Database> getDatabaseInstance() async {
final String databasesPath = await getDatabasesPath();
final String path = join(databasesPath, '<YOUR DB NAME>');
return await openDatabase(path, version: 1, onCreate: _onCreate);
}
Future<int> save(Contact contact) {
return getDatabaseInstance().then((db) {
final Map<String, dynamic> contactMap = Map();
contactMap['name'] = contact.name;
contactMap['account_number'] = contact.accountNumber;
return db.insert('contacts', contactMap);
});
}
The SQFlite page gives a good example about it and helps a lot.
https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_db.md
I'm trying to hook up my react native login with the backend. I use axios ^0.16.2 to call the API, but it always returns me 'Error: Request failed with status code 400'
What I have:
export const loginUser = ({ email, password }) => {
return (dispatch) => {
axios.post('http://localhost:8080/api/users/login',
{
email,
password
},
{
Accept: 'application/json',
'Content-Type': 'application/json',
}
)
.then(response => {
console.log(response);
dispatch({
type: LOGIN_USER,
payload: response.data.status
});
Actions.home();
})
.catch(error => {
console.log(error);
dispatch({
type: LOGIN_USER,
payload: error
});
}
);
};
};
Edit:
Pretty sure the request body is correct because the database has all the correct info.
I attached the API I have here, I used Java Spring Boot:
#Controller
#RequestMapping(value = "api/users", produces = {MediaType.APPLICATION_JSON_VALUE})
public class UserController {
/**
* Log a user in
* #param request
* #return
* #throws DuplicatedUserException
* #throws InvalidRequestException
*/
public static class UserLoginRequest implements ValiatedRequest {
private String username;
private Integer gmtShift;
private String email;
private String password;
#Override
public void validate() throws InvalidRequestException {
if (email == null || email.isEmpty()) {
throw new InvalidRequestException("email is empty.");
}
if (gmtShift == null || gmtShift < -12 || gmtShift > +12) {
throw new InvalidRequestException("gmtShift is empty or invalid.");
}
if (username == null || username.isEmpty()) {
throw new InvalidRequestException("user name is empty.");
}
if (password == null || password.isEmpty()) {
throw new InvalidRequestException("password is empty.");
}
if (!RegexUtil.EMAIL.matcher(email).find()) {
throw new InvalidRequestException("email is invalid.");
}
if (password.length() > 32) {
throw new InvalidRequestException("password cannot be longer than 32 characters.");
}
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getGmtShift() {
return gmtShift;
}
public void setGmtShift(Integer gmtShift) {
this.gmtShift = gmtShift;
}
}
#RequestMapping(value = "login", consumes = {MediaType.APPLICATION_JSON_VALUE}, method = RequestMethod.POST)
#ResponseBody
public Response loginUser(
#RequestBody UserLoginRequest request) throws AuthenticationException,
InvalidRequestException {
request.validate();
userService.authenticate(RequestContextHolder.currentRequestAttributes().getSessionId(),
request.getGmtShift(),
request.getUsername(),
request.getEmail(),
request.getPassword());
return new Response(Status.Success);
}
}
}
It may be possible that you are not sending the request in a proper way. I was also getting the same error, but some how I managed to fix the issue.
I am adding my code, hope this will help someone.
axios.post('Api Url',
{
'firstName': firstNameValue,
'lastName': lastNameValue,
'stateId': stateValue,
'email': emailValue,
'password': passwordValue,
'deviceInfo': deviceInfo
},{
"headers": {
'Content-Type': 'application/json',
}
}).then((response) => {
console.log("reactNativeDemo","response get details:"+response.data);
})
.catch((error) => {
console.log("axios error:",error);
});
I got it!
import qs.js;
with this code:
axios.post(Uri,Qs.stringify(data))
.then(function(result){})
.catch(function(error){});
Because your API get para by " #RequestBody" or "#RequestParam"!