How to setup a base URL and where do I declare it in flutter dio for api calls?

9,546

Solution 1

You can create app_config.dart file and manage different environments like below:

const _baseUrl = "baseUrl";

enum Environment { dev, stage, prod }

Map<String, dynamic> _config;

void setEnvironment(Environment env) {
  switch (env) {
    case Environment.dev:
      _config = devConstants;
      break;
    case Environment.stage:
      _config = stageConstants;
      break;
    case Environment.prod:
      _config = prodConstants;
      break;
  }
}

dynamic get apiBaseUrl {
  return _config[_baseUrl];
}

Map<String, dynamic> devConstants = {
  _baseUrl: "https://devapi.xyz.com/",
};


Map<String, dynamic> stageConstants = {
  _baseUrl: "https://api.stage.com/",
};

Map<String, dynamic> prodConstants = {
  _baseUrl: "https://api.production.com/",
};

Solution 2

Maybe instead of statically declaring your Dio object you could put it in a class, also put your loginUser function in there, and use Provider to obtain that object to call it where you need it.

class Api {
  static var uri = "https://xxx/xxx/web_api/public";
  static BaseOptions options = BaseOptions(
  baseUrl: uri,
  responseType: ResponseType.plain,
  connectTimeout: 30000,
  receiveTimeout: 30000,
  // ignore: missing_return
  validateStatus: (code) {
    if (code >= 200) {
      return true;
    }
  }); 
  Dio dio = Dio(options);

  Future<dynamic> loginUser(String email, String password) async {
    try {
      RequestOptions options = RequestOptions(
        headers: {"Content-Type": "application/json"},
      );
    Response response = await dio.post('/login',
        data: {
          "email": email,
          "password": password,
          "user_type": 2,
          "status": 1
        },
        options: options);
    //the rest of your code here
}

https://pub.dev/packages/provider

Provider(
  create: (_) => Api(),
  child: ...
)

https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html

YourWidget(
  child: Consumer<Api>(
    builder: (context, api, child) {
      return FutureBuilder<dynamic>(
      future: api.loginUser('[email protected]', 'user_password')
      builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
        if (snapshot.hasData) {
          //show a widget based on snapshot.data
        } else {
          //show another widget
        }
      }
    },
  ),
)
Share:
9,546
Sanjeevi Raj
Author by

Sanjeevi Raj

Updated on December 23, 2022

Comments

  • Sanjeevi Raj
    Sanjeevi Raj over 1 year

    like how to fix boilerplate code in separate file and use it in ui pages.

    I Need to declare this uri variable in separate file and access across over all pages:

      static var uri = "https://xxx/xxx/web_api/public";
      static BaseOptions options = BaseOptions(
      baseUrl: uri,
      responseType: ResponseType.plain,
      connectTimeout: 30000,
      receiveTimeout: 30000,
      // ignore: missing_return
      validateStatus: (code) {
        if (code >= 200) {
          return true;
        }
      });  static Dio dio = Dio(options);
    

    In UI page i have to declare that uri variable and BaseOption variable in this future function:

       Future<dynamic> _loginUser(String email, String password) async {
         try {
      Options options = Options(
        headers: {"Content-Type": "application/json"},
      );
      Response response = await dio.post('/login',
          data: {
            "email": email,
            "password": password,
            "user_type": 2,
            "status": 1
          },
          options: options);
    
      if (response.statusCode == 200 || response.statusCode == 201) {
        var responseJson = json.decode(response.data);
        return responseJson;
      } else if (response.statusCode == 401) {
        throw Exception("Incorrect Email/Password");
      } else
        throw Exception('Authentication Error');
    } on DioError catch (exception) {
      if (exception == null ||
          exception.toString().contains('SocketException')) {
        throw Exception("Network Error");
      } else if (exception.type == DioErrorType.RECEIVE_TIMEOUT ||
          exception.type == DioErrorType.CONNECT_TIMEOUT) {
        throw Exception(
            "Could'nt connect, please ensure you have a stable network.");
      } else {
        return null;
      }
    }
    

    }

  • Sanjeevi Raj
    Sanjeevi Raj over 3 years
    Thank You @Er1
  • William Chou
    William Chou about 3 years
    How would you call setEnvironment?
  • Aanal Shah
    Aanal Shah about 3 years
    @WilliamChou We are having 3 environments: development, stage, production. We have 3 dart files which sets the current environment based on flavours. 1) main_dev.dart, 2) main_stage.dart, 3) main_prod.dart. So, based on selected flavour, we will set the environment in the dart file.
  • Aanal Shah
    Aanal Shah about 3 years
    @WilliamChou Let me know if you require any help.