6

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
  • 81
  • 1
  • 3
  • 6
  • 1
    It's not clear what the problem is. The base url seems to be setup correctly `baseUrl: uri,`. You can then use a `FutureBuilder` widget to use `_loginUser` after you make it public (assuming it's in a different file) by renaming to to `loginUser`. – Er1 Aug 18 '20 at 09:32
  • the base url boilerplate code need to be in separate page not in a same page and from that class uri and option variables passed across all pages that uses apis:like – Sanjeevi Raj Aug 18 '20 at 10:11
  • Response response = await dio.post('Uri+/login', data: { "email": email, "password": password, "user_type": 2, "status": 1 }, options: options);@Er1 – Sanjeevi Raj Aug 18 '20 at 10:12
  • [link](https://stackoverflow.com/questions/23522407/how-to-setup-a-base-url-and-where-do-i-declare-it) – Sanjeevi Raj Aug 18 '20 at 10:19
  • Please accept the below answer if it's useful for you. So, we can save the time of others :) @SanjeeviRaj – Aanal Shah Mar 26 '21 at 05:54

3 Answers3

9

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/",
};
Aanal Shah
  • 1,946
  • 2
  • 20
  • 30
  • How would you call setEnvironment? – William Chou Apr 18 '21 at 12:50
  • @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 Apr 19 '21 at 11:54
  • @WilliamChou Let me know if you require any help. – Aanal Shah Apr 19 '21 at 11:55
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('mail@mail.com', 'user_password')
      builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
        if (snapshot.hasData) {
          //show a widget based on snapshot.data
        } else {
          //show another widget
        }
      }
    },
  ),
)
Er1
  • 2,559
  • 1
  • 12
  • 24
0

I set domain and env values in .env file. Then I read it using dotenv pacckage

local.env

env=local
apidomain=localhost:8000

dev.env

env=dev
apidomain=xyz.com

Following function gives url (http or https) based on environment. It uses domain based on environment too

import 'package:flutter_dotenv/flutter_dotenv.dart';

Uri getCompleteUrl({required String url}) {
  // if local env then http else https url
  String domain = dotenv.get('apidomain'); // localhost:8000 or xyz.com
  if (dotenv.get('env') == 'local') {
    return Uri.http(domain, url);
  } else {
    return Uri.https(domain, url);
  }
}
Aseem
  • 5,848
  • 7
  • 45
  • 69