Flutter Boilerplate containing pre initialised services and following standardised protocol for code quality.
Maintained by - Abhijeet Tripathi
| Feature | Availability | 
|---|---|
| Ready to use | ✅ | 
| MVVM based | ✅ | 
| Network services | ✅ | 
| Using Providers | ✅ | 
| Modular | ✅ | 
| Assets and custom Fonts | ✅ | 
| Embedded custom URL screen | ✅ | 
- Clone this repo
 
    git clone https://github.com/joshsoftware/flutter-boilerplate.git- 
Rename "flutter-boilerplate" folder to your "project_name"
 - 
Open folder in Android Studio
 - 
Open project's pubspec.yaml and change // This is Flutter level project name do not consider this as bundle id or application id
- "name: flutter_mvvm_boilerplate" to "name: project_name"
 - "description: Ready to use flutter boiler plate" to "description: Your project description"
 
 - 
In Android Studio's Terminal run
 
flutter pub getNote: You'll start getting errors in all your files it's because we've changed the flutter package name and imports are still directing to old package name.
- 
Right click on "lib" folder and click "Replace in path" and replace "flutter_mvvm_boilerplate" to "project_name" (same as you used in pubspec.yaml) click "Replace All". Note: Most of your errors will go away if not just close and reopen Android Studio once.
 - 
Change Application name and ID: Open terminal tab in Android Studio and run following commands.
 
• This will install package rename tool
flutter pub global activate rename • This will rename your Application name
flutter pub global run rename --appname "Project Name"• This will rename your Application ID/Bundle ID
flutter pub global run rename --bundleId com.companyname.projectname- Add and register project specific assets and you're ready to go.
 
Description
Maintainability is achieved by distributing type of Constant Data into specific category. Important constants files are
- 
api_constants.dart
- Contains base URL and all the end points that application is going to use.
 
 - 
app_constants.dart
- Contains maintenance flag for changing Production and Staging Environments
 - Also contains app related constants
 
 - 
singleton_constants.dart
- This is a Singleton class for general purpose data sharing over the app User object, token etc.
 
 - 
Other constants files are self explanatory
 
Description
Base Response Model is designed for productive API integration. This model can be modified according to Project's API structure.
File name
- response_data_model.dart
 
Keys to change
- Data
 - Error and Message
 - okAndContainsData
 
Based on your API Structure change the 'data' key to specified key where all your response's data will be delivered. Example: For given API structure
{
'data': [
  {
    'name': 'Abhijeet Tripathi',
    'mail': '[email protected]'
  }
{
    'name': 'Shekhar Sahu',
    'mail': '[email protected]'
  }
],
'message' : 'Data fetched',
'error' : 'None till now'
}the keys will be..
data: parsedJson['data'] != null ? parsedJson['data'] : null,
okAndContainsData: (response.statusCode == 200 ) && (parsedJson['data'] != null),
message: parsedJson['message'] != null ? parsedJson['message'] : "",Though this model is null safe but it's not safe from parsing errors.
Always cross checks key names and hierarchy of them.
Description
Networking layer is preinitialised with following features.
- Network connection check
 - Common loader
 - Common Error and Success Message
 - Prettyfied Logs for easy debugging.
 
Responsible files
- api_helper.dart
 - api_service.dart
 - api_constants.dart
 - network_check.dart
 - pretty_json_print.dart
 
Things to change
In api_helper.dart change the following as per your project needs.
- DEFAULT_TIMEOUT this is a top level variable denotes time out seconds. Default is 45.
 - _getHeaders this is Header generator for API call change as per required.
 - _handleError this is error handler for all REST calls you can handle unauthorised logout and error alert directly from here.
 
Usage example
- Declare end point you want consume in api_constants.dart in given format.
 
static const String LOGIN = "/api/login";- Create URI with base URL and end point in your function
 
//  baseURL here is Getter of String type that returns your base URL from
//  api_constants.dart and is directly accesibile.
Uri _loginUri = Uri.parse(baseURL + ApiConstants.LOGIN);- Use ApiHelper class it contains plug and play REST callers
 - ApiHelper have 2 types of caller
- Plug and Play This requires BuildContext and contains common loader and alert dialog built in
 - BG : This doesn't requires context can be called in Background but it doesn't contains UI elements everything will be handled by developer.
 
 
Map map =  { "email": "[email protected]","password": "cityslicka" }
// If showConnectivityError is set to false will Throw NoNetworkException in case of no connectivity.
// showConnectivityError: false allows developer to handle no connectivity exception manually.
// Plug and Play with common loader and dialog
ResponseData responseData =  
   await ApiHelper().postRequest(context, _loginUri, map,  
         useAuth: false, showLoader: true, responseName: "Login",
         showLog: true, showError: true, showConnectivityError: true); 
// Background callers without loader and dialog
// Throws NoNetworkException in case of no nonnectivity.
try {  
 ResponseData responseData =  
   await ApiHelper().postRequestBG(_loginUri,map,useAuth: false,showLog: true);
} on NoNetworkException {  
     print("Please Check Internet Connection");  
     //Handle error on UI if using BG callers  
}
- Check response and consume.
 
if (responseData.okAndContainsData ) {
   print(responseData.data['message'])
   // Do success stuff here.
}else if(responseData.statusCode == 500){
   // Handle 500.
}else{
   // Handle everthing else.
}
Description
Navigation is straight forward
Responsible file
- navigation_helper.dart
 
- Always provide Navigation TAG - All views have their own specific tag
 
static const String TAG = "/LoginView";These tags help to easily access and switch to views
- Register path in routes - in main.dart register paths to their respective view.
 
routes: {  
LoginView.TAG: (context) => NavigationHelper.getLoginViewWithProvider(),  
},- Keep Function naming standard
 
///Naming Standard:  
///Fun that gives View with provider             - getViewNameWithProvider()  
///Fun that pushes View                          - gotoViewName() 
///Fun that return Data				 - gotoViewNameWithResult()
///Fun(Data data) that pushes View with data     - gotoViewNameWithData(data)  
///Fun that clears stack and pushes View         - clearAndGotoViewName()