New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
General improvements from my fork #12
Comments
Pull request is really appreciated. @devkabiir |
Why use When I wanted to add normal methods to the annotated class, a compilation error occurred.😵 |
Extending classes is very tricky. It would require a lot of conditional code generation and a lot of testing edge cases. Because you can never really know how the user will create a new object of type Now for your use case of adding normal instance methods, you can create extensions for your // MyRestClient is the name of your custom rest client
// If you're not sure about extensions in dart, there are plenty of articles available online if you search for "extension methods in dart"
extension SpecialMethods on MyRestClient {
void myMethod(){}
Future<void> asyncMethod() async {}
// Literally any kind of method, getter and setter are supported.
}
|
@devkabiir you are correct. For that reason I added some logic to keep both implements and extends in generator depending on how programmer designes annoted class. https://github.com/trevorwang/retrofit.dart/pull/236/files#diff-c32d94163bf53716580c4c7c7effcf0bR76 https://github.com/trevorwang/retrofit.dart/pull/236/files#diff-c32d94163bf53716580c4c7c7effcf0bR89 And if not empty then https://github.com/trevorwang/retrofit.dart/pull/236/files#diff-c32d94163bf53716580c4c7c7effcf0bR114 And for you query related to Here's an example how this can be used to increase the flixibility: |
This smells bad code hygiene to me. In your example use case onedrive_api.dart. All of your additional methods could've been extension methods as specified in my previous example. Your only valid use case for using In your PR #236 You aren't handling default values for constructor parameters as well as parameters marked with the new The generated class becomes If someone uses your final apiForUser1 = OneDriveAPI(/* credentials */); What if they want to logout the user? They have to create a new instance of An alternative solution for providing // Approach one
mixin DioWithCredentials on Dio {
AccessCredentials get credentials;
}
// Approach two
mixin DioWithAutoUpdatingCredentials on Dio {
AccessCredentials _credentials;
AccessCredentials get credentials => _credentials ?? throw StateError('You have to set credentials first');
set credentials(AccessCredentials newCredentials){
options.headers['Authorization'] = newCredentials.authorization;
_credentials = newCredentials;
}
}
// Using Approach one
@RestApi(baseUrl: API_BASE_URL)
abstract class OneDriveAPI {
factory OneDriveAPI(DioWithCredentials dio) =>
_OneDriveApi(dio..options.headers['Authorization']=dio.credentials.authorization);
}
// Using Approach two
@RestApi(baseUrl: API_BASE_URL)
abstract class OneDriveAPI {
factory OneDriveAPI(DioWithAutoUpdatingCredentials dio, AccessCredentials credentials) => _OneDriveApi(dio..credentials = credentials);
}
Now it's upto the user of your API to use the provided Approach two also allows your users to change the credentials dynamically anytime they want using There are many more ways to solve the problem without changing the generated class to |
Any call to the RestApi would happen via the abstract layer of annoted class only, so it's immaterial to use required on parameters of the generated class. Moreover the generated class doesn't use any fields or concrete methods added to the annoted class, so the safety of those params or methods are the duty of the annoted class designer. As, I was trying to build a easy to use, type safe API for Onedrive using dart, that's why I didn't keep the direct access of dio open to the user using my package. OneDriveAPI is the entry point for the api and all the calls and errors relevant to dio will be handled underneath. Though it's not complete yet. |
I have made some general improvements in my fork. If you like those improvements, I'll send you a PR :).
Edit: my improvements include
Using
const
for things that are constants instead offinal
Add
@override
annotation as a conventionExample:
+ @override Future<Response<Account>> createAccount({Account data}) async {...}
Removed type information from generated methods, Dart can automatically infer the types from the super class devkabiir/retrofit.dart@ea051356ac24d85a932bf68f80c3a5fdc37c5073
Example:
Use forwarding/redirecting constructor instead of
instance()
static methodExample:
Don't add check for
baseUrl
beingnull
because it's a constant and we can know that at build-time devkabiir/retrofit.dart@f5664c7a58d12ec396bb0b83d7993ca3f48ab1daExample:
Add
ArgumentError.checkNotNull
for required parameters devkabiir/retrofit.dart@6c675756e2eedf943d0263b0f940a99373a0bedbGenerate
*.g.dart
shared parts instead of*.retrofit.dart
partsImplement the annotated class instead of extending it
Example:
Don't assign defaultValue if it's null for parameters devkabiir/retrofit.dart@a610e2675c84376c56f9568b9c5f1476b9995596
Add
@Extra
for passing extra options to requestOptions devkabiir/retrofit.dart@1d470c296efc46c0e500e60287ed187a3244b60aExample:
myapi.dart
@http.POST('/account/') + @dio.Extra({'myKey': 'myValue'}) Future<Response<Account>> createAccount( {@required @http.Body() Account data});
myapi.g.dart
The text was updated successfully, but these errors were encountered: