NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #440 most downloaded on pub.dev
Open screens/snackbars/dialogs without context, manage states and inject dependencies easily with GetX.
Last release 3 months ago
03 Jun 2026
Ships fairly regularly
a new release about every 5 months
Most releases are documented
notes for 48 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
7 years old
332 releases · first in 2019
Added: more multipart options. Now you can send as multipart:
File: 'file':MultipartFile(File('./images/avatar.png'), filename: 'avatar.png'),
String path: 'file':MultipartFile('./images/avatar.png', filename: 'avatar.png'),
Or bytes (Flutter web work only with bytes): 'file':MultipartFile(File('file').readAsBytesSync(), filename: 'avatar.png'),
Improve multipart file and defaultDecoder on GetConnect
One column per quarter.
Fix GetConnect.request returning a PUT request
Allow null body to POST method on GetConnect
This update attaches two nice features developed by (@SchabanBo): _GetPage Children_ And _GetMiddleware_ In previous versions, to create child pages,
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:
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.
The Order of the Middlewares to run can pe set by the priority in the GetMiddleware.
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
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.
GetPage redirect( ) {
final authService = Get.find<AuthService>();
return authService.authed.value ? null : RouteSettings(name: '/login')
}
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
GetPage onPageCalled(GetPage page) {
final authService = Get.find<AuthService>();
return page.copyWith(title: 'Welcome ${authService.UserName}');
}
This function will be called right before the Bindings are initialize. Here you can change Bindings for this page.
List<Bindings> onBindingsStart(List<Bindings> bindings) {
final authService = Get.find<AuthService>();
if (authService.isAdmin) {
bindings.add(AdminBinding());
}
return bindings;
}
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.
GetPageBuilder onPageBuildStart(GetPageBuilder page) {
print('bindings are ready');
return page;
}
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.
This function will be called right after disposing all the related objects (Controllers, views, ...) of the page.
Fix wrong reference with unnamed routes and added more tests
GetConnect is an easy way to communicate from your back to your front. With it you can:
Allow list.assignAll, map.assignAll and set.assignAll operate with null values
Added initial suport to navigator 2.0
Clean RxList, RxMap and RxSet implementation
RxList(), it will be started empty. If you want to start a null RxList, you must use RxList(null).
Improved GetStream to receive the same parameters as the StreamController, such as onListen, onPause, onResume and onCancel.Fix compilation error on master
Documentation translated into Russian language. (@Renat Fakhrutdinov, @Doaxan and @BatttA)
void main() {
var controller = StreamController(sync: true);
var stream = controller.stream;
stream.listen((data) {
print('$data');
if (data == 'test4') controller.add('test5');
});
print('test1');
controller.add('test2');
stream.listen((event) {}); // second listen throws a exception
print('test3');
controller.add('test4');
print('test6');
controller.add('test7');
print("test8");
}
2- Even with a single listener, the dart's Synchronous Streams api cannot deliver events in the exact order. We plan to work on a PR in the future at dart-lang to address this. So if we remove the line above that causes the exception, we will have the following output in the log:
void main() {
var controller = StreamController(sync: true);
var stream = controller.stream;
stream.listen((data) {
print('$data');
if (data == 'test4') controller.add('test5');
});
print('test1');
controller.add('test2');
// stream.listen((event) {}); // second listen throws a exception
print('test3');
controller.add('test4');
print('test6');
controller.add('test7');
print("test8");
}
///////////////////// log:
test1
test2
test3
test4
test6
test8
test5
As we can see, test 4 skips to test 6, which skips to test 8, which skips to test 5. Note that test 7 didn't even appear in the log.
However, if we work with GetStream, everything works as expected:
void main() {
var controller = GetStream();
var stream = controller.stream;
stream.listen((data) {
print('$data');
if (data == 'test4') controller.add('test5');
});
print('test1');
controller.add('test2');
// stream.listen((event) {}); // second listen throws a exception
print('test3');
controller.add('test4');
print('test6');
controller.add('test7');
print("test8");
}
///////////////////// log:
test1
test2
test3
test4
test5
test6
test7
test8
The dart documentation is clear that this api should be used with caution, and in view of these tests, we were sure that it is not stable enough to be used as the core of our state management, nor of the websockets notifications and get_server requests.
Clarification about the controversy over benchmarks: In a version prior to changeLog, we talked about the 9000% difference in performance between Streams, and GetStreams that ended up causing a lot of controversy in the community. Initially, we would like to clarify that this does not mean that you will have mobile applications 9000% faster. Only that one of our main resources, showed itself with a high rate of requests, 9000% faster than using traditional streams. In a real world scenario, you will hardly have so many simultaneous requests. Skia renders frames on new devices at up to 120fps. This means that if you have a 10 second animation, you will have 1200 reconstructions. Unless you are working with animations, or something that requires rendering at the skia boundary, you won't need that much power. So this does not mean that we are revolutionizing the mobile world, only that we have created an alternative to Stream Sincronas, which works as expected, and which has satisfactory performance for low latency resources. The benchmarks are real, but that does not mean that you will have mobile applications 9000% faster, but that you have a new feature that performs at this level to use. For reference only, the benchmark can be found (HERE)
In short: asynchronous streams from dart work perfectly, but add a latency that we want to remove on Get_server. Synchronous dart streams have unexpected behaviors, cannot have more than 1 listener and do not deliver events in the correct order, which completely prevents their use in mobile state managements, since you run the risk of displaying data on the wrong screen, since the last event will not always be the last event entered by the sink. The 9000% figures are real, however, they refer to the gross performance between Streams and GetStreams. This does not mean that this number will impact your applications, because you are unlikely to use all of that power.
Improve Performance: We made modifications to make GetBuilder even faster. We have improved the structure behind it so that listeners are notified fas
Reunification of the package. During the 2 week period, we try to keep this package as a compilation of smaller packages. We were successful in separa
Remove spaces whitespaces from dart files -
Fix typos on code and docs (@wbemanuel and @Goddchen)
Remove spaces whitespaces from dart files
Added BottomSheet Duration && Export SingleGetTickerProvider (@unacorbatanegra)
- Fix docs
Refactor structure from scratch to split GetX completely into separate packages. When using the main package (get) you will have everything working pe
Fixed the use of tags with lazyPut and added Ability to overwrite "tag" in GetView and GetWidget.
- Fix analyzer
Getx 3.10 released with CLI and Get Server.
Getx 3.10 released with CLI and Get Server.
Added: Snackbar Status: Open, Opening, Closing and Closed example:
Get.snackbar('title', 'message', snackbarStatus: (status) {
if (status == SnackbarStatus.CLOSED) {
// made anything
}
});
Added: RxSet. Sets can now also be reactive.
RxList list = [].obs;
And you use
List list = [].obs;.value can be used exclusively in ModelClasses.
Example:var name = "Jonny" .obs;
// usage:
Text ("$name");
var count = 0.obs;
// usage:
increment() => count ++;
Text("$count");
Thus: List, Map, Set, num, int, double and String, as of this release, will no longer use the .value property.
NOTE: The changes were not break changes, however, you may have missed the details of the documentation, so if you faced the message: "The member 'value' can only be used within instance members of subclasses of 'rx_list.dart' "you just need to remove the" .value "property from your list, and everything will work as planned. The same goes for Maps and Sets.
- Fix more formatting issues
- Fix formatting issues
Change default logger to developer.log (@jorgegaticav)
- Remove unnecessary whitespaces
Added responsiveValue (@juanjoseleca)
Fix TextField dispose throw on last Flutter hotfix
Fix typo on RxList.remove that could cause type errors.
Fix exception 'isInit called null' when tags are used in conjunction with dependencies. (@djade007)
Fix onInit fired only first time
- Fix individual imports
Structure organization, and improvements.
Added '[everAll]' Worker: Listen a List of '.obx'
Added CPF to utils options (@kauemurakami)
Get.lazyPut<Controller>(()=> Controller(), fenix:true) to have a controller that after being destroyed, has the ability to be recreated in case someone needs it. This is a function that already exists in smartManagement.keepFactory which is now also possible in full mode.Improve transitions and refactor route system
Prevent black blackground on cupertino fullscreenDialog
Added method update to Rx Now you no longer need to make an entire class reactive to get an element update from it, you can simply call the update met
class User{
User(this.name = '', this.age = 0);
String name;
int age;
}
final user = User().obs;
Obx(()=> Text("Name ${user.value.name}: Age: ${user.value.age}"))
// To update:
user.update((user){
user.name = 'Jonny';
user.age = 18;
});
Now is also possible to access a value without using the ".value". Just open and close parentheses. In the previous example, you could do:
user().name; // before: user.value.name
And it is also possible to set a value without using the value, inserting the value directly into the variable.
user(User('João', 35)); // before: user.value = User('João', 35)
Added fenix mode to Get.lazyPut.
- Update readme banner
Activate unknownRoute on version 3
- Expose GetInstance
- Improvement .obs methods
Added extensions to GetUtils and fix typo on GetUtils.isEmail (@stefandevo)
Breaking changes on Rx api and GetController and RxController were merged, and now you only have the 'GetxController'
Nothing published for this version
Nothing published for this version
Nothing published for this version
Added Duration on Get.offAll(@kluverua)
Prepared the framework for version 3
- Added Get.focusScope
Nothing published for this version
- Update readme
Nothing published for this version
Prevent exceptions on onReady with nullables
- Fix Workers
Added: onReady on Controllers LifeCycle
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →