Jonny Borges
Committed by GitHub

Bump to 2.11.2

## [2.11.2]
- Added docs
- Improvement performance of Obx
## [2.11.1]
- Fixed: oninit calling only once.
... ...
... ... @@ -667,7 +667,7 @@ Obviously, if someone wants to contribute to the project and create a code gener
Typing in Get using Bindings is unnecessary. you can use the Obx widget instead of GetX which only receives the anonymous function that creates a widget.
Obviously, if you don't use a type, you will need to have an instance of your controller to use the variables, or use `Get.find<Controller>()` .value or Controller.to.value to retrieve the value.
### GetX vs GetBuilder vs Obx MixinBuilder
### GetX vs GetBuilder vs Obx vs MixinBuilder
In a decade working with programming I was able to learn some valuable lessons.
My first contact with reactive programming was so "wow, this is incredible" and in fact reactive programming is incredible.
However, it is not suitable for all situations. Often all you need is to change the state of 2 or 3 widgets at the same time, or an ephemeral change of state, in which case reactive programming is not bad, but it is not appropriate.
... ... @@ -764,6 +764,23 @@ Get.to(Home(), binding: HomeBinding());
There, you don't have to worry about memory management of your application anymore, Get will do it for you.
The Binding class is called when a route is called, you can create an "initialBinding in your GetMaterialApp to insert all the dependencies that will be created.
```dart
GetMaterialApp(
initialBinding: SampleBind(),
home: Home();
);
```
If you want to use your initializations in one place, you can use SmartManagement.keepfactory to allow this, and although using keepfactory should be the exception, as it is the softest SmartManagement out there.
I always prefer the standard SmartManagement (full). It can be annoying at times, and eliminate something you don't want, as it has refined controls that remove memory dependency even if there is a flaw, and a widget is not arranged properly. It is safe enough with StatelessWidget, since even if there is no page available, it will still remove the controller from memory. But there are some use cases, which this restriction can be bothersome. For these situations you can use SmartManagement.onlyBuilders, which will depend on the effective removal of widgets that use the controller from the tree to remove the controller.
- NOTE: DO NOT USE SmartManagement.keepFactory if you are using multiple Bindings. It was designed to be used without Bindings, or with a single Binding linked in the GetBaterialApp's initialBinding.
- NOTE2: Using Bindings is completely optional, you can use Get.put() and Get.find() on classes that use a given controller without any problem.
However, if you work with Services or any other abstraction, I recommend using Bindings for a larger organization.
## Workers:
Workers will assist you, triggering specific callbacks when an event occurs.
... ... @@ -1062,7 +1079,7 @@ You don't need the context, and you will find your navigation stack by Id.
See how simple it is:
```dart
Navigator(
key: nestedKey(1), // create a key by index
key: Get.nestedKey(1), // create a key by index
initialRoute: '/',
onGenerateRoute: (settings) {
if (settings.name == '/') {
... ... @@ -1146,7 +1163,7 @@ Get.offNamedUntil() // go to next named route and remove all the previous routes
GetPlatform.isAndroid/isIOS/isWeb... //(This method is completely compatible with FlutterWeb, unlike the framework. "Platform.isAndroid")
Get.height / Get.width // Equivalent to the method: MediaQuery.of(context).size.height
Get.height / Get.width // Equivalent to the method: MediaQuery.of(context).size.height, but they are immutable. If you need a changeable height/width (like browser windows that can be scaled) you will need to use context.height and context.width
Get.context // Gives the context of the screen in the foreground anywhere in your code.
... ...
... ... @@ -755,7 +755,7 @@ class Get {
bool callInit = false;
if (Get.isRegistred<S>(tag: tag)) {
if (!isDependencyInit<S>() &&
Get().smartManagement == SmartManagement.full) {
Get().smartManagement != SmartManagement.onlyBuilder) {
Get().registerRouteInstance<S>(tag: tag);
callInit = true;
}
... ... @@ -781,7 +781,7 @@ class Get {
S _value = Get.put<S>(Get()._factory[key].call() as S);
if (!isDependencyInit<S>() &&
Get().smartManagement == SmartManagement.full) {
Get().smartManagement != SmartManagement.onlyBuilder) {
Get().registerRouteInstance<S>(tag: tag);
callInit = true;
}
... ... @@ -902,13 +902,6 @@ class Get {
/// give current arguments
static Map<String, String> get parameters => Get()._parameters;
/// interface to GetX
RxInterface _obs;
static RxInterface get obs => Get()._obs;
static set obs(RxInterface observer) => Get()._obs = observer;
/// give name from current route
static get currentRoute => Get()._routing.current;
... ... @@ -1005,6 +998,8 @@ class _FcBuilder<S> {
}
}
typedef _FcBuilderFunc<S> = S Function();
typedef _FcBuilderFuncAsync<S> = Future<S> Function();
... ...
... ... @@ -94,7 +94,7 @@ class GetObserver extends NavigatorObserver {
if (Get.isLogEnable) print("[BACK ROUTE] ${route?.settings?.name}");
}
if (Get().smartManagement == SmartManagement.full) {
if (Get().smartManagement != SmartManagement.onlyBuilder) {
Get().removeDependencyByRoute("${route?.settings?.name}");
}
... ...
... ... @@ -43,7 +43,9 @@ class _GetXState<T extends DisposableInterface> extends State<GetX<T>> {
bool isRegistred = Get.isRegistred<T>();
if (widget.global) {
if (isPrepared) {
isCreator = true;
if (Get().smartManagement != SmartManagement.keepFactory) {
isCreator = true;
}
controller = Get.find<T>();
} else if (isRegistred) {
controller = Get.find<T>();
... ... @@ -62,26 +64,19 @@ class _GetXState<T extends DisposableInterface> extends State<GetX<T>> {
if (isCreator && Get().smartManagement == SmartManagement.onlyBuilder) {
controller?.onInit();
}
_observer.subject.stream.listen((data) {
setState(() {});
});
_observer.subject.stream.listen((data) => setState(() {}));
super.initState();
}
@override
void dispose() {
if (widget.dispose != null) widget.dispose(this);
if (isCreator || widget.assignId) {
if (widget.autoRemove && Get.isRegistred<T>()) {
// controller.onClose();
Get.delete<T>();
}
// } else {
// controller.onClose();
}
// controller.onClose();
_observer.close();
controller = null;
isCreator = null;
... ... @@ -90,10 +85,10 @@ class _GetXState<T extends DisposableInterface> extends State<GetX<T>> {
@override
Widget build(BuildContext context) {
final observer = Get.obs;
Get.obs = this._observer;
final observer = getObs;
getObs = this._observer;
final result = widget.builder(controller);
Get.obs = observer;
getObs = observer;
return result;
}
}
... ...
import 'dart:async';
import 'package:get/src/get_main.dart';
import 'rx_callbacks.dart';
import 'rx_interface.dart';
import 'rx_model.dart';
... ... @@ -11,8 +10,8 @@ class _RxImpl<T> implements RxInterface<T> {
T _value;
T get v {
if (Get.obs != null) {
Get.obs.addListener(subject.stream);
if (getObs != null) {
getObs.addListener(subject.stream);
}
return _value;
}
... ... @@ -111,16 +110,8 @@ class MapX<Map> extends _RxImpl<Map> {
}
}
// class ListX<List> extends _RxImpl<List> {
// ListX([List initial]) {
// _value = initial;
// _onChange = subject.stream.asBroadcastStream();
// }
// }
/// Create a list similar to `List<T>`
class ListX<E> extends Iterable<E> implements RxInterface<E> {
/// Create a list similar to `List<T>`
ListX([List<E> initial]) {
_list = initial;
_onChange = subject.stream.asBroadcastStream();
... ... @@ -159,7 +150,7 @@ class ListX<E> extends Iterable<E> implements RxInterface<E> {
operator []=(int index, E val) {
_list[index] = val;
subject.add(Change<E>.set($new: val, item: val, pos: index));
subject.add(Change<E>.set($new: val, pos: index));
}
E operator [](int index) {
... ... @@ -168,13 +159,12 @@ class ListX<E> extends Iterable<E> implements RxInterface<E> {
void add(E item) {
_list.add(item);
subject
.add(Change<E>.insert($new: item, item: item, pos: _list.length - 1));
subject.add(Change<E>.insert($new: item, pos: _list.length - 1));
}
void addAll(List<E> item) {
_list.addAll(item);
subject.add(Change<E>.insert(item: _list, pos: _list.length - 1));
subject.add(Change<E>.insert($new: _list, pos: _list.length - 1));
}
/// Adds only if [item] is not null.
... ... @@ -189,12 +179,12 @@ class ListX<E> extends Iterable<E> implements RxInterface<E> {
void insert(int index, E item) {
_list.insert(index, item);
subject.add(Change<E>.insert(item: item, pos: index));
subject.add(Change<E>.insert($new: item, pos: index));
}
void insertAll(int index, Iterable<E> iterable) {
_list.insertAll(index, iterable);
subject.add(Change<E>.insert(item: iterable.last, pos: index));
subject.add(Change<E>.insert($new: iterable.last, pos: index));
}
int get length => value.length;
... ... @@ -208,32 +198,32 @@ class ListX<E> extends Iterable<E> implements RxInterface<E> {
int pos = _list.indexOf(item);
bool hasRemoved = _list.remove(item);
if (hasRemoved) {
subject.add(Change<E>.remove(item: item, pos: pos));
subject.add(Change<E>.remove($new: item, pos: pos));
}
return hasRemoved;
}
E removeAt(int index) {
E item = _list.removeAt(index);
subject.add(Change<E>.remove(item: item, pos: index));
subject.add(Change<E>.remove($new: item, pos: index));
return item;
}
E removeLast() {
int pos = _list.indexOf(_list.last);
E item = _list.removeLast();
subject.add(Change<E>.remove(item: item, pos: pos));
subject.add(Change<E>.remove($new: item, pos: pos));
return item;
}
void removeRange(int start, int end) {
_list.removeRange(start, end);
subject.add(Change<E>.remove(item: null, pos: null));
subject.add(Change<E>.remove($new: null, pos: null));
}
void removeWhere(bool Function(E) test) {
_list.removeWhere(test);
subject.add(Change<E>.remove(item: null, pos: null));
subject.add(Change<E>.remove($new: null, pos: null));
}
void clear() {
... ... @@ -287,8 +277,8 @@ class ListX<E> extends Iterable<E> implements RxInterface<E> {
@override
get v {
if (Get.obs != null) {
Get.obs.addListener(subject.stream);
if (getObs != null) {
getObs.addListener(subject.stream);
}
return _list;
}
... ... @@ -298,7 +288,7 @@ class ListX<E> extends Iterable<E> implements RxInterface<E> {
}
@override
Stream<E> get stream => onChange.map((c) => c.item);
Stream<E> get stream => onChange.map((c) => c.$new);
@override
void bind(RxInterface<E> reactive) {
... ... @@ -329,205 +319,12 @@ class ListX<E> extends Iterable<E> implements RxInterface<E> {
List<E> _list = <E>[];
}
// class ListX<E> extends DelegatingList<E> implements List<E>, RxInterface<E> {
// /// Create a list similar to `List<T>`
// ListX([int length]) : super(length != null ? List<E>(length) : List<E>()) {
// _onChange = subject.stream.asBroadcastStream();
// }
// ListX.filled(int length, E fill, {bool growable: false})
// : super(List<E>.filled(length, fill, growable: growable)) {
// _onChange = subject.stream.asBroadcastStream();
// }
// ListX.from(Iterable<E> items, {bool growable: true})
// : super(List<E>.from(items, growable: growable)) {
// _onChange = subject.stream.asBroadcastStream();
// }
// ListX.union(Iterable<E> items, [E item]) : super(items?.toList() ?? <E>[]) {
// if (item != null) add(item);
// _onChange = subject.stream.asBroadcastStream();
// }
// ListX.of(Iterable<E> items, {bool growable: true})
// : super(List<E>.of(items, growable: growable));
// ListX.generate(int length, E generator(int index), {bool growable: true})
// : super(List<E>.generate(length, generator, growable: growable));
// Map<Stream<Change<E>>, StreamSubscription> _subscriptions = Map();
// // StreamSubscription _changectl = StreamSubscription();
// StreamController<Change<E>> _changeCtl =
// StreamController<Change<E>>.broadcast();
// @override
// StreamController<Change<E>> subject = StreamController<Change<E>>.broadcast();
// /// Adds [item] only if [condition] resolves to true.
// void addIf(condition, E item) {
// if (condition is Condition) condition = condition();
// if (condition is bool && condition) add(item);
// }
// /// Adds all [items] only if [condition] resolves to true.
// void addAllIf(condition, Iterable<E> items) {
// if (condition is Condition) condition = condition();
// if (condition is bool && condition) addAll(items);
// }
// operator []=(int index, E value) {
// super[index] = value;
// if (Get.obs != null) {
// Get.obs.addListener(subject.stream);
// }
// subject.add(Change<E>.set(item: value, pos: index));
// }
// void _add(E item) => super.add(item);
// void add(E item) {
// super.add(item);
// subject.add(Change<E>.insert(item: item, pos: length - 1));
// }
// /// Adds only if [item] is not null.
// void addNonNull(E item) {
// if (item != null) add(item);
// }
// void insert(int index, E item) {
// super.insert(index, item);
// subject.add(Change<E>.insert(item: item, pos: index));
// }
// bool remove(Object item) {
// int pos = indexOf(item);
// bool hasRemoved = super.remove(item);
// if (hasRemoved) {
// subject.add(Change<E>.remove(item: item, pos: pos));
// }
// return hasRemoved;
// }
// void clear() {
// super.clear();
// subject.add(Change<E>.clear());
// }
// close() {
// clear();
// _subscriptions.forEach((observable, subscription) {
// subscription.cancel();
// });
// _subscriptions.clear();
// subject.close();
// _changeCtl.close();
// }
// /// Replaces all existing items of this list with [item]
// void assign(E item) {
// clear();
// add(item);
// }
// /// Replaces all existing items of this list with [items]
// void assignAll(Iterable<E> items) {
// clear();
// addAll(items);
// }
// /// A stream of record of changes to this list
// Stream<Change<E>> get onChange {
// final now = DateTime.now();
// _onChange.skipWhile((m) => m.time.isBefore(now));
// return _changeCtl.stream.asBroadcastStream();
// }
// Stream<Change<E>> _onChange;
// addListener(Stream<Change<E>> rxGetx) {
// if (_subscriptions.containsKey(rxGetx)) {
// return;
// }
// _subscriptions[rxGetx] = rxGetx.listen((data) {
// subject.add(data);
// });
// }
// List<E> get value => v as List<E>;
// set value(List<E> va) => assignAll(va);
// @override
// get v {
// if (Get.obs != null) {
// Get.obs.addListener(subject.stream);
// }
// return this;
// }
// set v(E val) {
// assign(val);
// }
// @override
// Stream<E> get stream => onChange.map((c) => c.item);
// @override
// void bind(RxInterface<E> reactive) {
// v = reactive.v;
// reactive.stream.listen((va) => v = va);
// }
// void bindStream(Stream<E> stream) => stream.listen((va) => v = va);
// @override
// void bindOrSet(/* T | Stream<T> or Rx<T> */ other) {
// if (other is RxInterface<E>) {
// bind(other);
// } else if (other is Stream<E>) {
// bindStream(other.cast<E>());
// } else {
// v = other;
// }
// }
// @override
// StreamSubscription<E> listen(ValueCallback<E> callback) =>
// stream.listen(callback);
// @override
// void setCast(dynamic val) => v = val;
// }
RxInterface getObs;
typedef bool Condition();
typedef E ChildrenListComposer<S, E>(S value);
// /// An observable list that is bound to another list [binding]
// class BindingList<S, E> extends ListX<E> {
// final ListX<S> binding;
// final ChildrenListComposer<S, E> composer;
// BindingList(this.binding, this.composer) {
// for (S v in binding) _add(composer(v));
// binding.onChange.listen((Change<S> n) {
// if (n.op == ListChangeOp.add) {
// insert(n.pos, composer(n.item));
// } else if (n.op == ListChangeOp.remove) {
// removeAt(n.pos);
// } else if (n.op == ListChangeOp.clear) {
// clear();
// }
// });
// }
// }
class BoolX<bool> extends _RxImpl<bool> {
BoolX([bool initial]) {
_value = initial;
... ...
... ... @@ -3,9 +3,9 @@ class Change<T> {
final T $old;
/// Value after change
final T $new;
final $new;
final item;
final ListChangeOp op;
... ... @@ -17,7 +17,7 @@ class Change<T> {
{this.$new,
this.$old,
this.batch,
this.item,
this.op,
this.pos,
DateTime time})
... ... @@ -25,24 +25,24 @@ class Change<T> {
String toString() => 'Change(new: ${$new}, old: ${$old})';
Change.insert(
{this.$new, this.$old, this.batch, this.item, this.pos, DateTime time})
{this.$new, this.$old, this.batch, this.pos, DateTime time})
: op = ListChangeOp.add,
time = time ?? new DateTime.now();
Change.set(
{this.$new, this.$old, this.batch, this.item, this.pos, DateTime time})
{this.$new, this.$old, this.batch, this.pos, DateTime time})
: op = ListChangeOp.set,
time = time ?? new DateTime.now();
Change.remove(
{this.$new, this.$old, this.batch, this.item, this.pos, DateTime time})
{this.$new, this.$old, this.batch, this.pos, DateTime time})
: op = ListChangeOp.remove,
time = time ?? new DateTime.now();
Change.clear({this.$new, this.$old, this.batch, DateTime time})
: op = ListChangeOp.clear,
pos = null,
item = null,
time = time ?? new DateTime.now();
}
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/rx/rx_interface.dart';
import '../get_main.dart';
import 'rx_impl.dart';
Widget obx(Widget Function() builder) {
... ... @@ -8,7 +7,7 @@ Widget obx(Widget Function() builder) {
return Obxx(b);
}
/// it's very very very very experimental, or now, it's just tests.
/// it's very very very very experimental
class Obxx extends StatelessWidget {
final Widget Function() builder;
Obxx(this.builder, {Key key}) : super(key: key);
... ... @@ -17,10 +16,10 @@ class Obxx extends StatelessWidget {
@override
Widget build(_) {
_observer.subject.stream.listen((data) => (_ as Element)..markNeedsBuild());
final observer = Get.obs;
Get.obs = _observer;
final observer = getObs;
getObs = _observer;
final result = builder();
Get.obs = observer;
getObs = observer;
return result;
}
}
... ... @@ -41,9 +40,7 @@ class _ObxState extends State<Obx> {
@override
void initState() {
_observer.subject.stream.listen((data) {
setState(() {});
});
_observer.subject.stream.listen((data) => setState(() {}));
super.initState();
}
... ... @@ -55,10 +52,10 @@ class _ObxState extends State<Obx> {
@override
Widget build(BuildContext context) {
final observer = Get.obs;
Get.obs = this._observer;
final observer = getObs;
getObs = _observer;
final result = widget.builder();
Get.obs = observer;
getObs = observer;
return result;
}
}
... ...
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:get/src/root/smart_management.dart';
import 'package:get/src/rx/rx_interface.dart';
import '../get_main.dart';
... ... @@ -69,12 +70,11 @@ class _GetBuilderState<T extends GetController> extends State<GetBuilder<T>> {
bool isRegistred = Get.isRegistred<T>();
if (isPrepared) {
isCreator = true;
if (Get().smartManagement != SmartManagement.keepFactory) {
isCreator = true;
}
controller = Get.find<T>();
real = RealState(
updater: setState,
id: widget.id,
);
real = RealState(updater: setState, id: widget.id);
controller._allStates.add(real);
} else if (isRegistred) {
controller = Get.find<T>();
... ... @@ -84,7 +84,6 @@ class _GetBuilderState<T extends GetController> extends State<GetBuilder<T>> {
} else {
controller = widget.init;
isCreator = true;
real = RealState(updater: setState, id: widget.id);
controller._allStates.add(real);
Get.put<T>(controller);
... ... @@ -97,9 +96,9 @@ class _GetBuilderState<T extends GetController> extends State<GetBuilder<T>> {
controller?.onInit();
}
if (widget.initState != null) widget.initState(this);
// if (isCreator) {
// controller?.onInit();
// }
if (isCreator && Get().smartManagement == SmartManagement.onlyBuilder) {
controller?.onInit();
}
}
@override
... ...
name: get
description: Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get.
version: 2.11.1
version: 2.11.2
homepage: https://github.com/jonataslaw/get
environment:
... ...