new change to use intaleq_map sdk 04-16-4
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../get.dart';
|
||||
|
||||
/// Unlike GetxController, which serves to control events on each of its pages,
|
||||
/// GetxService is not automatically disposed (nor can be removed with
|
||||
/// Get.delete()).
|
||||
/// It is ideal for situations where, once started, that service will
|
||||
/// remain in memory, such as Auth control for example. Only way to remove
|
||||
/// it is Get.reset().
|
||||
abstract class GetxService extends DisposableInterface with GetxServiceMixin {}
|
||||
|
||||
abstract class DisposableInterface extends GetLifeCycle {
|
||||
/// Called immediately after the widget is allocated in memory.
|
||||
/// You might use this to initialize something for the controller.
|
||||
@override
|
||||
@mustCallSuper
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
|
||||
Get.engine.addPostFrameCallback((_) => onReady());
|
||||
}
|
||||
|
||||
/// Called 1 frame after onInit(). It is the perfect place to enter
|
||||
/// navigation events, like snackbar, dialogs, or a new route, or
|
||||
/// async request.
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
/// Called before [onDelete] method. [onClose] might be used to
|
||||
/// dispose resources used by the controller. Like closing events,
|
||||
/// or streams before the controller is destroyed.
|
||||
/// Or dispose objects that can potentially create some memory leaks,
|
||||
/// like TextEditingControllers, AnimationControllers.
|
||||
/// Might be useful as well to persist some data on disk.
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import '../../../get_core/get_core.dart';
|
||||
import '../../../get_instance/src/get_instance.dart';
|
||||
import '../../../get_rx/src/rx_types/rx_types.dart';
|
||||
import '../../get_state_manager.dart';
|
||||
|
||||
typedef GetXControllerBuilder<T extends DisposableInterface> = Widget Function(
|
||||
T controller);
|
||||
|
||||
class GetX<T extends DisposableInterface> extends StatefulWidget {
|
||||
final GetXControllerBuilder<T> builder;
|
||||
final bool global;
|
||||
|
||||
// final Stream Function(T) stream;
|
||||
// final StreamController Function(T) streamController;
|
||||
final bool autoRemove;
|
||||
final bool assignId;
|
||||
final void Function(GetXState<T> state)? initState,
|
||||
dispose,
|
||||
didChangeDependencies;
|
||||
final void Function(GetX oldWidget, GetXState<T> state)? didUpdateWidget;
|
||||
final T? init;
|
||||
final String? tag;
|
||||
|
||||
const GetX({
|
||||
this.tag,
|
||||
required this.builder,
|
||||
this.global = true,
|
||||
this.autoRemove = true,
|
||||
this.initState,
|
||||
this.assignId = false,
|
||||
// this.stream,
|
||||
this.dispose,
|
||||
this.didChangeDependencies,
|
||||
this.didUpdateWidget,
|
||||
this.init,
|
||||
// this.streamController
|
||||
});
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties
|
||||
..add(
|
||||
DiagnosticsProperty<T>('controller', init),
|
||||
)
|
||||
..add(DiagnosticsProperty<String>('tag', tag))
|
||||
..add(
|
||||
ObjectFlagProperty<GetXControllerBuilder<T>>.has('builder', builder));
|
||||
}
|
||||
|
||||
@override
|
||||
GetXState<T> createState() => GetXState<T>();
|
||||
}
|
||||
|
||||
class GetXState<T extends DisposableInterface> extends State<GetX<T>> {
|
||||
final _observer = RxNotifier();
|
||||
T? controller;
|
||||
bool? _isCreator = false;
|
||||
late StreamSubscription _subs;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// var isPrepared = GetInstance().isPrepared<T>(tag: widget.tag);
|
||||
final isRegistered = GetInstance().isRegistered<T>(tag: widget.tag);
|
||||
|
||||
if (widget.global) {
|
||||
if (isRegistered) {
|
||||
_isCreator = GetInstance().isPrepared<T>(tag: widget.tag);
|
||||
controller = GetInstance().find<T>(tag: widget.tag);
|
||||
} else {
|
||||
controller = widget.init;
|
||||
_isCreator = true;
|
||||
GetInstance().put<T>(controller!, tag: widget.tag);
|
||||
}
|
||||
} else {
|
||||
controller = widget.init;
|
||||
_isCreator = true;
|
||||
controller?.onStart();
|
||||
}
|
||||
widget.initState?.call(this);
|
||||
if (widget.global && Get.smartManagement == SmartManagement.onlyBuilder) {
|
||||
controller?.onStart();
|
||||
}
|
||||
_subs = _observer.listen((data) => setState(() {}), cancelOnError: false);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
if (widget.didChangeDependencies != null) {
|
||||
widget.didChangeDependencies!(this);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(GetX oldWidget) {
|
||||
super.didUpdateWidget(oldWidget as GetX<T>);
|
||||
widget.didUpdateWidget?.call(oldWidget, this);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (widget.dispose != null) widget.dispose!(this);
|
||||
if (_isCreator! || widget.assignId) {
|
||||
if (widget.autoRemove && GetInstance().isRegistered<T>(tag: widget.tag)) {
|
||||
GetInstance().delete<T>(tag: widget.tag);
|
||||
}
|
||||
}
|
||||
_subs.cancel();
|
||||
_observer.close();
|
||||
controller = null;
|
||||
_isCreator = null;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(DiagnosticsProperty<T>('controller', controller));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => RxInterface.notifyChildren(
|
||||
_observer,
|
||||
() => widget.builder(controller!),
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
|
||||
import '../../../instance_manager.dart';
|
||||
import '../../get_state_manager.dart';
|
||||
import '../simple/list_notifier.dart';
|
||||
|
||||
mixin StateMixin<T> on ListNotifierMixin {
|
||||
T? _value;
|
||||
RxStatus? _status;
|
||||
|
||||
bool _isNullOrEmpty(dynamic val) {
|
||||
if (val == null) return true;
|
||||
var result = false;
|
||||
if (val is Iterable) {
|
||||
result = val.isEmpty;
|
||||
} else if (val is String) {
|
||||
result = val.isEmpty;
|
||||
} else if (val is Map) {
|
||||
result = val.isEmpty;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void _fillEmptyStatus() {
|
||||
_status = _isNullOrEmpty(_value) ? RxStatus.loading() : RxStatus.success();
|
||||
}
|
||||
|
||||
RxStatus get status {
|
||||
notifyChildrens();
|
||||
return _status ??= _status = RxStatus.loading();
|
||||
}
|
||||
|
||||
T? get state => value;
|
||||
|
||||
@protected
|
||||
T? get value {
|
||||
notifyChildrens();
|
||||
return _value;
|
||||
}
|
||||
|
||||
@protected
|
||||
set value(T? newValue) {
|
||||
if (_value == newValue) return;
|
||||
_value = newValue;
|
||||
refresh();
|
||||
}
|
||||
|
||||
@protected
|
||||
void change(T? newState, {RxStatus? status}) {
|
||||
var _canUpdate = false;
|
||||
if (status != null) {
|
||||
_status = status;
|
||||
_canUpdate = true;
|
||||
}
|
||||
if (newState != _value) {
|
||||
_value = newState;
|
||||
_canUpdate = true;
|
||||
}
|
||||
if (_canUpdate) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void append(Future<T> Function() body(), {String? errorMessage}) {
|
||||
final compute = body();
|
||||
compute().then((newValue) {
|
||||
change(newValue, status: RxStatus.success());
|
||||
}, onError: (err) {
|
||||
change(state, status: RxStatus.error(errorMessage ?? err.toString()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class Value<T> extends ListNotifier
|
||||
with StateMixin<T>
|
||||
implements ValueListenable<T?> {
|
||||
Value(T val) {
|
||||
_value = val;
|
||||
_fillEmptyStatus();
|
||||
}
|
||||
|
||||
@override
|
||||
T? get value {
|
||||
notifyChildrens();
|
||||
return _value;
|
||||
}
|
||||
|
||||
@override
|
||||
set value(T? newValue) {
|
||||
if (_value == newValue) return;
|
||||
_value = newValue;
|
||||
refresh();
|
||||
}
|
||||
|
||||
T? call([T? v]) {
|
||||
if (v != null) {
|
||||
value = v;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void update(void fn(T? value)) {
|
||||
fn(value);
|
||||
refresh();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => value.toString();
|
||||
|
||||
dynamic toJson() => (value as dynamic)?.toJson();
|
||||
}
|
||||
|
||||
extension ReactiveT<T> on T {
|
||||
Value<T> get reactive => Value<T>(this);
|
||||
}
|
||||
|
||||
typedef Condition = bool Function();
|
||||
|
||||
abstract class GetNotifier<T> extends Value<T> with GetLifeCycleBase {
|
||||
GetNotifier(T initial) : super(initial) {
|
||||
$configureLifeCycle();
|
||||
}
|
||||
|
||||
@override
|
||||
@mustCallSuper
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
ambiguate(SchedulerBinding.instance)
|
||||
?.addPostFrameCallback((_) => onReady());
|
||||
}
|
||||
}
|
||||
|
||||
extension StateExt<T> on StateMixin<T> {
|
||||
Widget obx(
|
||||
NotifierBuilder<T?> widget, {
|
||||
Widget Function(String? error)? onError,
|
||||
Widget? onLoading,
|
||||
Widget? onEmpty,
|
||||
}) {
|
||||
return SimpleBuilder(builder: (_) {
|
||||
if (status.isLoading) {
|
||||
return onLoading ?? const Center(child: CircularProgressIndicator());
|
||||
} else if (status.isError) {
|
||||
return onError != null
|
||||
? onError(status.errorMessage)
|
||||
: Center(child: Text('A error occurred: ${status.errorMessage}'));
|
||||
} else if (status.isEmpty) {
|
||||
return onEmpty != null
|
||||
? onEmpty
|
||||
: SizedBox.shrink(); // Also can be widget(null); but is risky
|
||||
}
|
||||
return widget(value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class RxStatus {
|
||||
final bool isLoading;
|
||||
final bool isError;
|
||||
final bool isSuccess;
|
||||
final bool isEmpty;
|
||||
final bool isLoadingMore;
|
||||
final String? errorMessage;
|
||||
|
||||
RxStatus._({
|
||||
this.isEmpty = false,
|
||||
this.isLoading = false,
|
||||
this.isError = false,
|
||||
this.isSuccess = false,
|
||||
this.errorMessage,
|
||||
this.isLoadingMore = false,
|
||||
});
|
||||
|
||||
factory RxStatus.loading() {
|
||||
return RxStatus._(isLoading: true);
|
||||
}
|
||||
|
||||
factory RxStatus.loadingMore() {
|
||||
return RxStatus._(isSuccess: true, isLoadingMore: true);
|
||||
}
|
||||
|
||||
factory RxStatus.success() {
|
||||
return RxStatus._(isSuccess: true);
|
||||
}
|
||||
|
||||
factory RxStatus.error([String? message]) {
|
||||
return RxStatus._(isError: true, errorMessage: message);
|
||||
}
|
||||
|
||||
factory RxStatus.empty() {
|
||||
return RxStatus._(isEmpty: true);
|
||||
}
|
||||
}
|
||||
|
||||
typedef NotifierBuilder<T> = Widget Function(T state);
|
||||
@@ -0,0 +1,92 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import '../../../get_rx/src/rx_types/rx_types.dart';
|
||||
|
||||
typedef WidgetCallback = Widget Function();
|
||||
|
||||
/// The [ObxWidget] is the base for all GetX reactive widgets
|
||||
///
|
||||
/// See also:
|
||||
/// - [Obx]
|
||||
/// - [ObxValue]
|
||||
abstract class ObxWidget extends StatefulWidget {
|
||||
const ObxWidget({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties..add(ObjectFlagProperty<Function>.has('builder', build));
|
||||
}
|
||||
|
||||
@override
|
||||
_ObxState createState() => _ObxState();
|
||||
|
||||
@protected
|
||||
Widget build();
|
||||
}
|
||||
|
||||
class _ObxState extends State<ObxWidget> {
|
||||
final _observer = RxNotifier();
|
||||
late StreamSubscription subs;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
subs = _observer.listen(_updateTree, cancelOnError: false);
|
||||
}
|
||||
|
||||
void _updateTree(_) {
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
subs.cancel();
|
||||
_observer.close();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
RxInterface.notifyChildren(_observer, widget.build);
|
||||
}
|
||||
|
||||
/// The simplest reactive widget in GetX.
|
||||
///
|
||||
/// Just pass your Rx variable in the root scope of the callback to have it
|
||||
/// automatically registered for changes.
|
||||
///
|
||||
/// final _name = "GetX".obs;
|
||||
/// Obx(() => Text( _name.value )),... ;
|
||||
class Obx extends ObxWidget {
|
||||
final WidgetCallback builder;
|
||||
|
||||
const Obx(this.builder);
|
||||
|
||||
@override
|
||||
Widget build() => builder();
|
||||
}
|
||||
|
||||
/// Similar to Obx, but manages a local state.
|
||||
/// Pass the initial data in constructor.
|
||||
/// Useful for simple local states, like toggles, visibility, themes,
|
||||
/// button states, etc.
|
||||
/// Sample:
|
||||
/// ObxValue((data) => Switch(
|
||||
/// value: data.value,
|
||||
/// onChanged: (flag) => data.value = flag,
|
||||
/// ),
|
||||
/// false.obs,
|
||||
/// ),
|
||||
class ObxValue<T extends RxInterface> extends ObxWidget {
|
||||
final Widget Function(T) builder;
|
||||
final T data;
|
||||
|
||||
const ObxValue(this.builder, this.data, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build() => builder(data);
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
|
||||
import '../../get_state_manager.dart';
|
||||
|
||||
/// Used like `SingleTickerProviderMixin` but only with Get Controllers.
|
||||
/// Simplifies AnimationController creation inside GetxController.
|
||||
///
|
||||
/// Example:
|
||||
///```
|
||||
///class SplashController extends GetxController with
|
||||
/// GetSingleTickerProviderStateMixin {
|
||||
/// AnimationController controller;
|
||||
///
|
||||
/// @override
|
||||
/// void onInit() {
|
||||
/// final duration = const Duration(seconds: 2);
|
||||
/// controller =
|
||||
/// AnimationController.unbounded(duration: duration, vsync: this);
|
||||
/// controller.repeat();
|
||||
/// controller.addListener(() =>
|
||||
/// print("Animation Controller value: ${controller.value}"));
|
||||
/// }
|
||||
/// ...
|
||||
/// ```
|
||||
mixin GetSingleTickerProviderStateMixin on GetxController
|
||||
implements TickerProvider {
|
||||
Ticker? _ticker;
|
||||
|
||||
@override
|
||||
Ticker createTicker(TickerCallback onTick) {
|
||||
assert(() {
|
||||
if (_ticker == null) return true;
|
||||
throw FlutterError.fromParts(<DiagnosticsNode>[
|
||||
ErrorSummary(
|
||||
'$runtimeType is a GetSingleTickerProviderStateMixin but multiple tickers were created.'),
|
||||
ErrorDescription(
|
||||
'A GetSingleTickerProviderStateMixin can only be used as a TickerProvider once.'),
|
||||
ErrorHint(
|
||||
'If a State is used for multiple AnimationController objects, or if it is passed to other '
|
||||
'objects and those objects might use it more than one time in total, then instead of '
|
||||
'mixing in a GetSingleTickerProviderStateMixin, use a regular GetTickerProviderStateMixin.',
|
||||
),
|
||||
]);
|
||||
}());
|
||||
_ticker =
|
||||
Ticker(onTick, debugLabel: kDebugMode ? 'created by $this' : null);
|
||||
// We assume that this is called from initState, build, or some sort of
|
||||
// event handler, and that thus TickerMode.of(context) would return true. We
|
||||
// can't actually check that here because if we're in initState then we're
|
||||
// not allowed to do inheritance checks yet.
|
||||
return _ticker!;
|
||||
}
|
||||
|
||||
void didChangeDependencies(BuildContext context) {
|
||||
if (_ticker != null) _ticker!.muted = !TickerMode.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
assert(() {
|
||||
if (_ticker == null || !_ticker!.isActive) return true;
|
||||
throw FlutterError.fromParts(<DiagnosticsNode>[
|
||||
ErrorSummary('$this was disposed with an active Ticker.'),
|
||||
ErrorDescription(
|
||||
'$runtimeType created a Ticker via its GetSingleTickerProviderStateMixin, but at the time '
|
||||
'dispose() was called on the mixin, that Ticker was still active. The Ticker must '
|
||||
'be disposed before calling super.dispose().',
|
||||
),
|
||||
ErrorHint(
|
||||
'Tickers used by AnimationControllers '
|
||||
'should be disposed by calling dispose() on the AnimationController itself. '
|
||||
'Otherwise, the ticker will leak.',
|
||||
),
|
||||
_ticker!.describeForError('The offending ticker was'),
|
||||
]);
|
||||
}());
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
/// Used like `TickerProviderMixin` but only with Get Controllers.
|
||||
/// Simplifies multiple AnimationController creation inside GetxController.
|
||||
///
|
||||
/// Example:
|
||||
///```
|
||||
///class SplashController extends GetxController with
|
||||
/// GetTickerProviderStateMixin {
|
||||
/// AnimationController first_controller;
|
||||
/// AnimationController second_controller;
|
||||
///
|
||||
/// @override
|
||||
/// void onInit() {
|
||||
/// final duration = const Duration(seconds: 2);
|
||||
/// first_controller =
|
||||
/// AnimationController.unbounded(duration: duration, vsync: this);
|
||||
/// second_controller =
|
||||
/// AnimationController.unbounded(duration: duration, vsync: this);
|
||||
/// first_controller.repeat();
|
||||
/// first_controller.addListener(() =>
|
||||
/// print("Animation Controller value: ${first_controller.value}"));
|
||||
/// second_controller.addListener(() =>
|
||||
/// print("Animation Controller value: ${second_controller.value}"));
|
||||
/// }
|
||||
/// ...
|
||||
/// ```
|
||||
mixin GetTickerProviderStateMixin on GetxController implements TickerProvider {
|
||||
Set<Ticker>? _tickers;
|
||||
|
||||
@override
|
||||
Ticker createTicker(TickerCallback onTick) {
|
||||
_tickers ??= <_WidgetTicker>{};
|
||||
final result = _WidgetTicker(onTick, this,
|
||||
debugLabel: kDebugMode ? 'created by ${describeIdentity(this)}' : null);
|
||||
_tickers!.add(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void _removeTicker(_WidgetTicker ticker) {
|
||||
assert(_tickers != null);
|
||||
assert(_tickers!.contains(ticker));
|
||||
_tickers!.remove(ticker);
|
||||
}
|
||||
|
||||
void didChangeDependencies(BuildContext context) {
|
||||
final muted = !TickerMode.of(context);
|
||||
if (_tickers != null) {
|
||||
for (final ticker in _tickers!) {
|
||||
ticker.muted = muted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
assert(() {
|
||||
if (_tickers != null) {
|
||||
for (final ticker in _tickers!) {
|
||||
if (ticker.isActive) {
|
||||
throw FlutterError.fromParts(<DiagnosticsNode>[
|
||||
ErrorSummary('$this was disposed with an active Ticker.'),
|
||||
ErrorDescription(
|
||||
'$runtimeType created a Ticker via its GetTickerProviderStateMixin, but at the time '
|
||||
'dispose() was called on the mixin, that Ticker was still active. All Tickers must '
|
||||
'be disposed before calling super.dispose().',
|
||||
),
|
||||
ErrorHint(
|
||||
'Tickers used by AnimationControllers '
|
||||
'should be disposed by calling dispose() on the AnimationController itself. '
|
||||
'Otherwise, the ticker will leak.',
|
||||
),
|
||||
ticker.describeForError('The offending ticker was'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}());
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
class _WidgetTicker extends Ticker {
|
||||
_WidgetTicker(TickerCallback onTick, this._creator, {String? debugLabel})
|
||||
: super(onTick, debugLabel: debugLabel);
|
||||
|
||||
final GetTickerProviderStateMixin _creator;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_creator._removeTicker(this);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('use GetSingleTickerProviderStateMixin')
|
||||
|
||||
/// Used like `SingleTickerProviderMixin` but only with Get Controllers.
|
||||
/// Simplifies AnimationController creation inside GetxController.
|
||||
///
|
||||
/// Example:
|
||||
///```
|
||||
///class SplashController extends GetxController with
|
||||
/// SingleGetTickerProviderMixin {
|
||||
/// AnimationController _ac;
|
||||
///
|
||||
/// @override
|
||||
/// void onInit() {
|
||||
/// final dur = const Duration(seconds: 2);
|
||||
/// _ac = AnimationController.unbounded(duration: dur, vsync: this);
|
||||
/// _ac.repeat();
|
||||
/// _ac.addListener(() => print("Animation Controller value: ${_ac.value}"));
|
||||
/// }
|
||||
/// ...
|
||||
/// ```
|
||||
mixin SingleGetTickerProviderMixin on DisposableInterface
|
||||
implements TickerProvider {
|
||||
@override
|
||||
Ticker createTicker(TickerCallback onTick) => Ticker(onTick);
|
||||
}
|
||||
Reference in New Issue
Block a user