Jonatas

update to 3.21.0

## [3.21.0] - Big update
- This update attaches two nice features developed by (@SchabanBo): *GetPage Children* And *GetMiddleware*
In previous versions, to create child pages, you should do something like:
```dart
GetPage(
name: '/home',
page: () => HomeView(),
binding: HomeBinding(),
),
GetPage(
name: '/home/products',
page: () => ProductsView(),
binding: ProductsBinding(),
),
GetPage(
name: '/home/products/electronics',
page: () => ElectronicsView(),
binding: ElectronicsBinding(),
),
```
Although the feature works well, it could be improved in several ways:
1- If you had many pages, the page file could become huge and difficult to read. Besides, it was difficult to know which page was the daughter of which module.
2- It was not possible to delegate the function of naming routes to a subroutine file.
With this update, it is possible to create a declarative structure, very similar to the Flutter widget tree for your route, which might look like this:
```dart
GetPage(
name: '/home',
page: () => HomeView(),
binding: HomeBinding(),
children: [
GetPage(
name: '/products',
page: () => ProductsView(),
binding: ProductsBinding(),
children: [
GetPage(
name: '/electronics',
page: () => ElectronicsView(),
binding: ElectronicsBinding(),
),
],
),
],
);
```
Thus, when accessing the url: '/home/products/electronics'
Or use Get.toNamed('/home/products/electronics') it will go directly to the page [ElectronicsView], because the child pages, automatically inherit the name of the ancestral page, so _with any small change on any father in the tree all children will be updated._ If you change [/products] to [/accessories], you don't nesse update on all child links.
However, the most powerful feature of this version is *GetMiddlewares*.
The GetPage has now new property that takes a list of GetMiddleWare than can perform actions and run them in the specific order.
### Priority
The Order of the Middlewares to run can pe set by the priority in the GetMiddleware.
```dart
final middlewares = [
GetMiddleware(priority: 2),
GetMiddleware(priority: 5),
GetMiddleware(priority: 4),
GetMiddleware(priority: -8),
];
```
those middlewares will be run in this order **-8 => 2 => 4 => 5**
### Redirect
This function will be called when the page of the called route is being searched for. It takes RouteSettings as a result to redirect to. Or give it null and there will be no redirecting.
```dart
GetPage redirect( ) {
final authService = Get.find<AuthService>();
return authService.authed.value ? null : RouteSettings(name: '/login')
}
```
### onPageCalled
This function will be called when this Page is called before anything created
you can use it to change something about the page or give it new page
```dart
GetPage onPageCalled(GetPage page) {
final authService = Get.find<AuthService>();
return page.copyWith(title: 'Welcome ${authService.UserName}');
}
```
### OnBindingsStart
This function will be called right before the Bindings are initialize.
Here you can change Bindings for this page.
```dart
List<Bindings> onBindingsStart(List<Bindings> bindings) {
final authService = Get.find<AuthService>();
if (authService.isAdmin) {
bindings.add(AdminBinding());
}
return bindings;
}
```
### OnPageBuildStart
This function will be called right after the Bindings are initialize.
Here you can do something after that you created the bindings and before creating the page widget.
```dart
GetPageBuilder onPageBuildStart(GetPageBuilder page) {
print('bindings are ready');
return page;
}
```
### OnPageBuilt
This function will be called right after the GetPage.page function is called and will give you the result of the function. and take the widget that will be showed.
### OnPageDispose
This function will be called right after disposing all the related objects (Controllers, views, ...) of the page.
## [3.20.1]
* Fix wrong reference with unnamed routes and added more tests
... ...
... ... @@ -38,6 +38,14 @@
- [GetConnect](#getconnect)
- [Default configuration](#default-configuration)
- [Custom configuration](#custom-configuration)
- [GetPage Middleware](#getpage-middleware)
- [Priority](#priority)
- [Redirect](#redirect)
- [onPageCalled](#onpagecalled)
- [OnBindingsStart](#onbindingsstart)
- [OnPageBuildStart](#onpagebuildstart)
- [OnPageBuilt](#onpagebuilt)
- [OnPageDispose](#onpagedispose)
- [Other Advanced APIs](#other-advanced-apis)
- [Optional Global Settings and Manual configurations](#optional-global-settings-and-manual-configurations)
- [Local State Widgets](#local-state-widgets)
... ... @@ -416,8 +424,6 @@ GetConnect is highly customizable You can define base Url, as answer modifiers,
class HomeProvider extends GetConnect {
@override
void onInit() {
@override
void onInit() {
// All request will pass to jsonEncode so CasesModel.fromJson()
httpClient.defaultDecoder = CasesModel.fromJson;
httpClient.baseUrl = 'https://api.covid19api.com';
... ... @@ -459,6 +465,83 @@ class HomeProvider extends GetConnect {
}
```
## GetPage Middleware
The GetPage has now new property that takes a list of GetMiddleWare and run them in the specific order.
**Note**: When GetPage has a Middlewares, all the children of this page will have the same middlewares automatically.
### Priority
The Order of the Middlewares to run can pe set by the priority in the GetMiddleware.
```dart
final middlewares = [
GetMiddleware(priority: 2),
GetMiddleware(priority: 5),
GetMiddleware(priority: 4),
GetMiddleware(priority: -8),
];
```
those middlewares will be run in this order **-8 => 2 => 4 => 5**
### Redirect
This function will be called when the page of the called route is being searched for. It takes RouteSettings as a result to redirect to. Or give it null and there will be no redirecting.
```dart
GetPage redirect( ) {
final authService = Get.find<AuthService>();
return authService.authed.value ? null : RouteSettings(name: '/login')
}
```
### onPageCalled
This function will be called when this Page is called before anything created
you can use it to change something about the page or give it new page
```dart
GetPage onPageCalled(GetPage page) {
final authService = Get.find<AuthService>();
return page.copyWith(title: 'Welcome ${authService.UserName}');
}
```
### OnBindingsStart
This function will be called right before the Bindings are initialize.
Here you can change Bindings for this page.
```dart
List<Bindings> onBindingsStart(List<Bindings> bindings) {
final authService = Get.find<AuthService>();
if (authService.isAdmin) {
bindings.add(AdminBinding());
}
return bindings;
}
```
### OnPageBuildStart
This function will be called right after the Bindings are initialize.
Here you can do something after that you created the bindings and before creating the page widget.
```dart
GetPageBuilder onPageBuildStart(GetPageBuilder page) {
print('bindings are ready');
return page;
}
```
### OnPageBuilt
This function will be called right after the GetPage.page function is called and will give you the result of the function. and take the widget that will be showed.
### OnPageDispose
This function will be called right after disposing all the related objects (Controllers, views, ...) of the page.
## Other Advanced APIs
... ...
... ... @@ -91,39 +91,39 @@ class GetHttpClient {
Map<String, dynamic> query,
Decoder<T> decoder,
) async {
assert(method != null);
assert(body != null);
List<int> bodyBytes;
BodyBytes bodyStream;
final headers = <String, String>{};
headers['content-type'] = contentType ?? defaultContentType;
headers['user-agent'] = userAgent;
if (body is FormData) {
bodyBytes = await body.toBytes();
} else {
try {
var jsonString = json.encode(body);
//TODO check this implementation
if (contentType != null) {
if (contentType.toLowerCase() ==
'application/x-www-form-urlencoded') {
var paramName = 'param';
jsonString = '$paramName=${Uri.encodeQueryComponent(jsonString)}';
}
headers['content-length'] = bodyBytes.length.toString();
} else if (body is Map || body is List) {
var jsonString = json.encode(body);
//TODO check this implementation
if (contentType != null) {
if (contentType.toLowerCase() == 'application/x-www-form-urlencoded') {
var paramName = 'param';
jsonString = '$paramName=${Uri.encodeQueryComponent(jsonString)}';
}
}
bodyBytes = utf8.encode(jsonString);
} on Exception catch (err) {
if (!errorSafety) {
throw UnexpectedFormat(err.toString());
} else {}
bodyBytes = utf8.encode(jsonString);
headers['content-length'] = bodyBytes.length.toString();
} else if (body == null) {
headers['content-length'] = '0';
} else {
if (!errorSafety) {
throw UnexpectedFormat('body cannot be ${body.runtimeType}');
}
}
final bodyStream = BodyBytes.fromBytes(bodyBytes);
final headers = <String, String>{};
_setHeadersWithBody(contentType, headers, bodyBytes);
if (bodyBytes != null) {
bodyStream = BodyBytes.fromBytes(bodyBytes);
}
final uri = _createUri(url, query);
... ... @@ -137,27 +137,6 @@ class GetHttpClient {
);
}
void _setHeadersWithBody(
String contentType,
// String jsonString,
Map<String, String> headers,
List<int> bodyBytes,
// List<MultipartFile> files,
) {
// if (files != null) {
// headers['content-type'] = 'multipart/form-data';
// headers['x-requested-with'] = 'XMLHttpRequest';
// } else {
// headers['content-type'] = contentType ?? defaultContentType;
// }
headers['content-type'] =
contentType ?? defaultContentType; // verify if this is better location
headers['user-agent'] = userAgent;
headers['content-length'] = bodyBytes.length.toString();
}
void _setSimpleHeaders(
Map<String, String> headers,
String contentType,
... ... @@ -249,9 +228,7 @@ class GetHttpClient {
@required dynamic body,
Map<String, dynamic> query,
Decoder<T> decoder,
// List<MultipartFile> files,
}) {
assert(body != null);
return _requestWithBody<T>(
url,
contentType,
... ... @@ -262,15 +239,24 @@ class GetHttpClient {
);
}
Future<Request<T>> _request<T>(
String url,
String method, {
String contentType,
@required dynamic body,
@required Map<String, dynamic> query,
Decoder<T> decoder,
}) {
return _requestWithBody(url, contentType, body, method, query, decoder);
}
Future<Request<T>> _put<T>(
String url, {
String contentType,
@required dynamic body,
@required Map<String, dynamic> query,
Decoder<T> decoder,
// List<MultipartFile> files,
}) {
assert(body != null);
return _requestWithBody(url, contentType, body, 'put', query, decoder);
}
... ... @@ -323,6 +309,41 @@ class GetHttpClient {
}
}
Future<Response<T>> request<T>(
String url,
String method, {
Map<String, dynamic> body,
String contentType,
Map<String, String> headers,
Map<String, dynamic> query,
Decoder<T> decoder,
}) async {
try {
var response = await _performRequest(
() => _request(
url,
method,
contentType: contentType,
query: query,
body: body,
decoder: decoder,
),
headers: headers,
);
return response;
} on Exception catch (e) {
if (!errorSafety) {
throw GetHttpException(e.toString());
}
return Future.value(Response<T>(
request: null,
statusCode: null,
body: null,
statusText: 'Can not connect to server. Reason: $e',
));
}
}
Future<Response<T>> put<T>(
String url,
Map<String, dynamic> body, {
... ...
... ... @@ -62,8 +62,8 @@ abstract class _RouteMiddleware {
/// This function will be called right after the [Bindings] are initialize.
GetPageBuilder onPageBuildStart(GetPageBuilder page);
/// This function will be called right after the
/// GetPage.page function is called and will give you the result
/// This function will be called right after the
/// GetPage.page function is called and will give you the result
/// of the function. and take the widget that will be showed.
Widget onPageBuilt(Widget page);
... ...
name: get
description: Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with GetX.
version: 3.20.1
version: 3.21.0
homepage: https://github.com/jonataslaw/getx
environment:
... ...