ydhnwb / resepmau_mvp_flutter

This is a flutter app with mvp architecture pattern. Features : Login, Register, and CRUD, logout
https://medium.com/@ydhnwb/pendekatan-mudah-flutter-mvp-with-retrofit-492c5bb27ed1
9 stars 4 forks source link

flutter: Exception DioError [DioErrorType.DEFAULT]: type 'String' is not a subtype of type 'Map<String, dynamic>' #3

Open BhavinMCT opened 4 years ago

BhavinMCT commented 4 years ago

I am new in flutter and I am not able to solve this issue can anyone help me? I am able to get data in string if I type Future<String> login() instead of Future<WrappedResponse> login() this and it will print on Presenter class which is given below.

This is my api class

import 'dart:io';
import 'dart:math';
import 'package:ceee_app/converters/wrapped_response.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:retrofit/retrofit.dart';

part 'api_service.g.dart';

@RestApi(baseUrl: "https://******.com/_dev/api/v1/")
abstract class RestClient {
  factory RestClient(Dio dio) = _RestClient;

  @FormUrlEncoded()
  @POST("login")
  Future<WrappedResponse> login(@Field("email") String email, @Field("password") String password, @Field("device_token") String token, @Field("device_type") String type);
}

This is my wrapper class

import 'package:ceee_app/model/user.dart';
import 'package:json_annotation/json_annotation.dart';

part 'wrapped_response.g.dart';

@JsonSerializable()

class WrappedResponse{
  @JsonKey(name: "message")
  String message;
  @JsonKey(name: "status")
  String status;
  @JsonKey(name: "result")
  User data;

  WrappedResponse();

  factory WrappedResponse.fromJson(Map<String, dynamic> json) => _$WrappedResponseFromJson(json);
  Map<String, dynamic> toJson() => _$WrappedResponseToJson(this);

}

This is my user class

import 'package:json_annotation/json_annotation.dart';

part "user.g.dart";

@JsonSerializable()
class User{
  @JsonKey()
  int id;
  @JsonKey()
  String name;
  @JsonKey()
  String l_name;
  @JsonKey()
  String email;
  @JsonKey()
  String session_token;
  @JsonKey()
  String device_token;

  User();

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);

  Map<String, dynamic> toJson() => _$UserToJson(this);

}

This is my Presenter class

import 'package:ceee_app/contracts/login_activity_contract.dart';
import 'package:ceee_app/model/user.dart';
import 'package:ceee_app/webservices/api_service.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:shared_preferences/shared_preferences.dart';

class LoginActivityPresenter implements LoginActivityInteractor {
  LoginActivityView view;
  LoginActivityPresenter(this.view);
  RestClient api = RestClient(Dio());

  @override
  void success(String token) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setString("api_token", token);
  }

  @override
  void destroy() => view = null;

  @override
  void login(String email, String password, String token, String type) async {
    await api.login(email, password, token, type).then((it){
      debugPrint("Data : "+it.toString());

    }).catchError((e){
      print("Exception $e");
      view?.toast("There is an error!");
    });
  }
}

And my response is

{
  "status": 1,
  "message": "Login successful!",
  "result": {
    "id": 20,
    "session_token": "YXBpX3Rva2VuNWY3YzJmODM2ZTgyNjUuNTY1MjUwNzAxNjAxOTc0MTQ3",
    "name": "abd",
    "l_name": "xyz",
    "email": "abc@gmail.com",
    "device_token": "fKrw8mpYT96fWIfaxrF26r:APA91bGZUW1wGSmdNMNb",
  }
}
ydhnwb commented 4 years ago

Looks like your api response have an Int in status key

status:1

Try to change the data type of status from String to Int in WrappedResponse

BhavinMCT commented 4 years ago

@ydhnwb thanks for your input but your suggestion want work , same error pops up. One thing I want to say is I created new project and code everything manually instead of json_serializable it will convert all json data into model class , So my thinking is to auto generated code not generated properly.

BhavinMCT commented 4 years ago

Hello @ydhnwb, After updating flutter I'll getting error in this file

import 'dart:io';
import 'dart:math';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_demo/converters/wrapped_response.dart';
import 'package:flutter_demo/models/User.dart';
import 'package:flutter_demo/models/UserHeadar.dart';
import 'package:retrofit/retrofit.dart';

part 'api_service.g.dart';

@RestApi(baseUrl: "https://telefitapp.com/telefit_dev/api/v1/")
abstract class RestClient {
  factory RestClient(Dio dio) = _RestClient;

  @POST("login")
  Future<WrappedResponse> login(@Field("email") String email,@Field("password") String password,@Field("device_type") String type,@Field("device_token") String token);
}

WrappedResponse class

import 'package:flutter_demo/models/User.dart';
import 'package:json_annotation/json_annotation.dart';

part 'wrapped_response.g.dart';

@JsonSerializable()
class WrappedResponse{
  @JsonKey(name: "message")
  String message;
  @JsonKey(name: "status")
  int status;
  @JsonKey(name: "result")
  User data;

  WrappedResponse(this.message, this.status, this.data);

  factory WrappedResponse.fromJson(Map<String, dynamic> json) => _$WrappedResponseFromJson(json);
  Map<String, dynamic> toJson() => _$WrappedResponseToJson(this);

}

Error on command "flutter packages pub run build_runner build --delete-conflicting-outputs"

[SEVERE] retrofit_generator:retrofit on lib/webservices/api_service.dart (cached):

Could not format because the source could not be parsed:

line 16, column 31: Expected an identifier.
   ╷
16 │ final value = WrappedResponse*.fromJson(_result.data);
   │                               ^
   ╵
[SEVERE] Failed after 933ms
pub finished with exit code 1