We have finished the functionality, but some tareto be missed. Mainly, we haven't followed the Dart style guide:
So, let's work on fixing these issues by running the automated fixes.
Running Automated Fixes and Fixing Dart Issues
Let's start our work by running the automated fixes. We can do this by running the following command:
dart fix --apply
And see how many issues it fixes:
That's not too bad! We went from 56 issues down to 25! That's a good start and a reminder that we should always run the automated fixes before pushing our code.
Fixing Manual Issues
But we still have 25 issues to fix manually. Let's start by looking at the list:
We can see that there's a recurring issue:
Don't invoke 'print' in production code.Try using a logging framework.
They are right—we should not leave print()
in our code. But for the sake of this tutorial, we will leave it in.
Let's work our way through the list:
The left operand can't be null, so the right operand is never executed. Try removing the operator and the right operand.
lib/providers/auth_provider.dart
// ...Future<String> getToken() async { try { String? token = await storage.read(key: 'token'); if (token != null) { return token ?? ''; } return ''; return token ?? ''; } catch (e) { return ''; }}
Unnecessary use of getter and setter to wrap a field. Try removing the getter and setter and renaming the field.
lib/models/category.dart
class Category { int _id; String _name; int get id => _id; set id(int id) => _id = id; String get name => _name; set name(String name) => _name = name; Category({required int id, required String name}) : _id = id, _name = name; factory Category.fromJson(Map<String, dynamic> json) { return Category(id: json['id'], name: json['name']); }} class Category { int? id; String name; Category({required this.id, required this.name}); factory Category.fromJson(Map<String, dynamic> json) { return Category(id: json['id'], name: json['name']); }}
Use an initializing formal to assign a parameter to a field. Try using an initialing formal ('this.authProvider') to initialize the field.
lib/providers/category_provider.dart
// ... class CategoryProvider extends ChangeNotifier { List<Category> categories = []; late ApiService apiService; late AuthProvider authProvider; CategoryProvider(AuthProvider authProvider) { this.authProvider = authProvider; authProvider = authProvider; apiService = ApiService(authProvider.token); init(); } // ...
Use an initializing formal to assign a parameter to a field. Try using an initialing formal ('this.authProvider') to initialize the field.
lib/providers/transaction_provider.dart
// ...class TransactionProvider extends ChangeNotifier { List<Transaction> transactions = []; late ApiService apiService; late AuthProvider authProvider; TransactionProvider(AuthProvider authProvider) { this.authProvider = authProvider; authProvider = authProvider;// init(); } // ...
The file name 'Login.dart' isn't a lower_case_with_underscores identifier. Try changing the name to follow the lower_case_with_underscores style. You may need to close the file and restart VS Code after renaming a file by only casing.
For this one, and in fact, Register too - we have to rename our files:
-
Login
->login
-
Register
->register
Then, in our lib/main.dart
, we have to change the Import:
import 'package:laravel_api_flutter_app/Screens/Auth/Login.dart';import 'package:laravel_api_flutter_app/Screens/Auth/login.dart';import 'package:laravel_api_flutter_app/Screens/Auth/Register.dart';import 'package:laravel_api_flutter_app/Screens/Auth/register.dart'; // ...
And restart your VSCode to apply the changes.
The parameter name 'Exception' matches a visible type name. Try adding a name for the parameter or changing the parameter name to not match an existing type.
lib/screens/Auth/login.dart
// ... Future<void> submit() async { final form = _formKey.currentState; if (!form!.validate()) { return; } final AuthProvider provider = Provider.of<AuthProvider>(context, listen: false); try { await provider.login( emailController.text, passwordController.text, deviceName); } catch (Exception) { } catch (e) { setState(() { errorMessage = Exception.toString().replaceAll('Exception: ', ''); errorMessage = e.toString().replaceAll('Exception: ', ''); }); }}
We have an identical issue on our Register
screen:
lib/screens/Auth/register.dart
Future<void> submit() async { final form = _formKey.currentState; if (!form!.validate()) { return; } final AuthProvider provider = Provider.of<AuthProvider>(context, listen: false); try { await provider.register( nameController.text, emailController.text, passwordController.text, confirmPasswordController.text, deviceName); Navigator.pop(context); } catch (Exception) { } catch (e) { setState(() { errorMessage = Exception.toString().replaceAll('Exception: ', ''); errorMessage = e.toString().replaceAll('Exception: ', ''); }); }}
We also made a mistake when we used an outdated Flutter code style. In this case:
Invalid use of a private type in a public API. Try making the private type public, or making the API that uses the private type also be private.
This means we have the _TransactionProvider
class, which should be public and named TransactionProvider
. So there's going to be a few places where we have to rename things:
-
lib/screens/home.dart -
_HomeState
->HomeState
-
lib/screens/transactions/list.dart -
_TransactionsState
->TransactionsState
-
lib/widgets/transaction_edit.dart -
_TransactionEditState
->TransactionEditState
-
lib/widgets/transaction_add.dart -
_TransactionAddState
->TransactionAddState
The last fix that is left is:
Use an initializing formal to assign a parameter to a field. Try using an initialing formal ('this.token') to initialize the field.
lib/services/api_service.dart
// ... class ApiService { late String token; ApiService(String token) { this.token = token; token = token; } // ...
That's it; we have fixed all the issues! The only one left should be about print()
usage, but that's okay.
We should use our application to see that everything works as expected.
In the next lesson, we will handle an exception when our Token expires. This is a common issue in applications that use tokens for authentication.
Check out the GitHub Commit for this lesson.
No comments yet…