Jonny Borges
Committed by GitHub

Merge pull request #1540 from kranfix/refactor/rx_interface_notify_children

Refactor/rx interface notify children
... ... @@ -80,3 +80,6 @@ example/macos/Flutter/ephemeral/Flutter-Generated.xcconfig
example/macos/Flutter/ephemeral/
example/macos/Flutter/GeneratedPluginRegistrant.swift
# Coverage files
coverage/
\ No newline at end of file
... ...
import 'package:example_nav2/app/modules/home/controllers/home_controller.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/home_controller.dart';
class DashboardView extends GetView<HomeController> {
@override
Widget build(BuildContext context) {
... ...
import 'package:example_nav2/app/models/demo_product.dart';
import 'package:get/get.dart';
import '../../../models/demo_product.dart';
class ProductsController extends GetxController {
final products = <DemoProduct>[].obs;
... ...
import 'package:example_nav2/app/routes/app_pages.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../routes/app_pages.dart';
import '../controllers/products_controller.dart';
class ProductsView extends GetView<ProductsController> {
... ...
import 'package:example_nav2/app/routes/app_pages.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../routes/app_pages.dart';
class DrawerWidget extends StatelessWidget {
const DrawerWidget({
Key? key,
... ...
import 'package:example_nav2/app/modules/root/bindings/root_binding.dart';
import 'package:example_nav2/app/modules/root/views/root_view.dart';
import 'package:get/get.dart';
import 'package:get/get_navigation/src/nav2/router_outlet.dart';
import '../modules/home/bindings/home_binding.dart';
import '../modules/home/views/home_view.dart';
import '../modules/product_details/bindings/product_details_binding.dart';
... ... @@ -10,6 +9,8 @@ import '../modules/products/bindings/products_binding.dart';
import '../modules/products/views/products_view.dart';
import '../modules/profile/bindings/profile_binding.dart';
import '../modules/profile/views/profile_view.dart';
import '../modules/root/bindings/root_binding.dart';
import '../modules/root/views/root_view.dart';
import '../modules/settings/bindings/settings_binding.dart';
import '../modules/settings/views/settings_view.dart';
... ...
import 'package:flutter/widgets.dart';
import '../../get_navigation/src/nav2/get_router_delegate.dart';
import '../../get_navigation/src/routes/get_route.dart';
import 'log.dart';
import 'smart_management.dart';
... ...
import 'dart:async';
import 'dart:collection';
import 'package:flutter/widgets.dart';
import '../../get_core/get_core.dart';
import 'lifecycle.dart';
... ...
... ... @@ -449,8 +449,10 @@ extension ExtensionBottomSheet on GetInterface {
modalBarrierColor: barrierColor,
settings: settings,
enableDrag: enableDrag,
enterBottomSheetDuration: enterBottomSheetDuration ?? const Duration(milliseconds: 250),
exitBottomSheetDuration: exitBottomSheetDuration ?? const Duration(milliseconds: 200),
enterBottomSheetDuration:
enterBottomSheetDuration ?? const Duration(milliseconds: 250),
exitBottomSheetDuration:
exitBottomSheetDuration ?? const Duration(milliseconds: 200),
));
}
}
... ...
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import '../../../get.dart';
/// This config enables us to navigate directly to a sub-url
class GetNavConfig extends RouteInformation {
... ...
import 'package:flutter/material.dart';
import 'package:get/get_navigation/src/nav2/get_router_delegate.dart';
import '../../../get.dart';
import 'get_router_delegate.dart';
class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object>
extends StatefulWidget {
... ...
... ... @@ -5,7 +5,6 @@ import 'package:flutter/material.dart';
import '../../../get_core/get_core.dart';
import '../../../get_instance/get_instance.dart';
import '../../../get_state_manager/get_state_manager.dart';
import '../../../get_state_manager/src/simple/list_notifier.dart';
import '../../../get_utils/get_utils.dart';
import '../../get_navigation.dart';
import 'root_controller.dart';
... ...
... ... @@ -105,9 +105,7 @@ mixin RxObjectMixin<T> on NotifyManager<T> {
/// Returns the current [value]
T get value {
if (RxInterface.proxy != null) {
RxInterface.proxy!.addListener(subject);
}
RxInterface.proxy?.addListener(subject);
return _value;
}
... ...
... ... @@ -18,4 +18,23 @@ abstract class RxInterface<T> {
/// Calls [callback] with current value, when the value changes.
StreamSubscription<T> listen(void Function(T event) onData,
{Function? onError, void Function()? onDone, bool? cancelOnError});
/// Avoids an unsafe usage of the `proxy`
static T notifyChildren<T>(RxNotifier observer, ValueGetter<T> builder) {
final _observer = RxInterface.proxy;
RxInterface.proxy = observer;
final result = builder();
if (!observer.canUpdate) {
throw """
[Get] the improper use of a GetX has been detected.
You should only use GetX or Obx for the specific widget that will be updated.
If you are seeing this error, you probably did not insert any observable variables into GetX/Obx
or insert them outside the scope that GetX considers suitable for an update
(example: GetX => HeavyWidget => variableObservable).
If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX.
""";
}
RxInterface.proxy = _observer;
return result;
}
}
... ...
... ... @@ -78,9 +78,7 @@ class RxList<E> extends ListMixin<E>
@override
@protected
List<E> get value {
if (RxInterface.proxy != null) {
RxInterface.proxy!.addListener(subject);
}
RxInterface.proxy?.addListener(subject);
return _value;
}
... ...
... ... @@ -56,9 +56,7 @@ class RxMap<K, V> extends MapMixin<K, V>
@override
@protected
Map<K, V> get value {
if (RxInterface.proxy != null) {
RxInterface.proxy!.addListener(subject);
}
RxInterface.proxy?.addListener(subject);
return _value;
}
}
... ...
... ... @@ -23,9 +23,7 @@ class RxSet<E> extends SetMixin<E>
@override
@protected
Set<E> get value {
if (RxInterface.proxy != null) {
RxInterface.proxy!.addListener(subject);
}
RxInterface.proxy?.addListener(subject);
return _value;
}
... ...
... ... @@ -45,10 +45,7 @@ class GetX<T extends DisposableInterface> extends StatefulWidget {
}
class GetXState<T extends DisposableInterface> extends State<GetX<T>> {
GetXState() {
_observer = RxNotifier();
}
RxInterface? _observer;
final _observer = RxNotifier();
T? controller;
bool? _isCreator = false;
late StreamSubscription _subs;
... ... @@ -56,15 +53,11 @@ class GetXState<T extends DisposableInterface> extends State<GetX<T>> {
@override
void initState() {
// var isPrepared = GetInstance().isPrepared<T>(tag: widget.tag);
var isRegistered = GetInstance().isRegistered<T>(tag: widget.tag);
final isRegistered = GetInstance().isRegistered<T>(tag: widget.tag);
if (widget.global) {
if (isRegistered) {
if (GetInstance().isPrepared<T>(tag: widget.tag)) {
_isCreator = true;
} else {
_isCreator = false;
}
_isCreator = GetInstance().isPrepared<T>(tag: widget.tag);
controller = GetInstance().find<T>(tag: widget.tag);
} else {
controller = widget.init;
... ... @@ -80,7 +73,7 @@ class GetXState<T extends DisposableInterface> extends State<GetX<T>> {
if (widget.global && Get.smartManagement == SmartManagement.onlyBuilder) {
controller?.onStart();
}
_subs = _observer!.listen((data) => setState(() {}), cancelOnError: false);
_subs = _observer.listen((data) => setState(() {}), cancelOnError: false);
super.initState();
}
... ... @@ -107,30 +100,15 @@ class GetXState<T extends DisposableInterface> extends State<GetX<T>> {
}
}
_subs.cancel();
_observer!.close();
_observer.close();
controller = null;
_isCreator = null;
super.dispose();
}
Widget get notifyChildren {
final observer = RxInterface.proxy;
RxInterface.proxy = _observer;
final result = widget.builder(controller!);
if (!_observer!.canUpdate) {
throw """
[Get] the improper use of a GetX has been detected.
You should only use GetX or Obx for the specific widget that will be updated.
If you are seeing this error, you probably did not insert any observable variables into GetX/Obx
or insert them outside the scope that GetX considers suitable for an update
(example: GetX => HeavyWidget => variableObservable).
If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX.
""";
}
RxInterface.proxy = observer;
return result;
}
@override
Widget build(BuildContext context) => notifyChildren;
Widget build(BuildContext context) => RxInterface.notifyChildren(
_observer,
() => widget.builder(controller!),
);
}
... ...
... ... @@ -20,17 +20,13 @@ abstract class ObxWidget extends StatefulWidget {
}
class _ObxState extends State<ObxWidget> {
RxInterface? _observer;
final _observer = RxNotifier();
late StreamSubscription subs;
_ObxState() {
_observer = RxNotifier();
}
@override
void initState() {
subs = _observer!.listen(_updateTree, cancelOnError: false);
super.initState();
subs = _observer.listen(_updateTree, cancelOnError: false);
}
void _updateTree(_) {
... ... @@ -42,30 +38,13 @@ class _ObxState extends State<ObxWidget> {
@override
void dispose() {
subs.cancel();
_observer!.close();
_observer.close();
super.dispose();
}
Widget get notifyChilds {
final observer = RxInterface.proxy;
RxInterface.proxy = _observer;
final result = widget.build();
if (!_observer!.canUpdate) {
throw """
[Get] the improper use of a GetX has been detected.
You should only use GetX or Obx for the specific widget that will be updated.
If you are seeing this error, you probably did not insert any observable variables into GetX/Obx
or insert them outside the scope that GetX considers suitable for an update
(example: GetX => HeavyWidget => variableObservable).
If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX.
""";
}
RxInterface.proxy = observer;
return result;
}
@override
Widget build(BuildContext context) => notifyChilds;
Widget build(BuildContext context) =>
RxInterface.notifyChildren(_observer, widget.build);
}
/// The simplest reactive widget in GetX.
... ...