if (!zone && fast) { obj->initInstanceIsa(cls, hasCxxDtor); } else { // Use raw pointer isa on the assumption that they might be // doing something weird with the zone or RR. obj->initIsa(cls); }
if (!zone && fast) { obj->initInstanceIsa(cls, hasCxxDtor); } else { // Use raw pointer isa on the assumption that they might be // doing something weird with the zone or RR. obj->initIsa(cls); }
/** Subscribes an element handler, an error handler, a completion handler and disposed handler to an observable sequence. - parameter onNext: Action to invoke for each element in the observable sequence. - parameter onError: Action to invoke upon errored termination of the observable sequence. - parameter onCompleted: Action to invoke upon graceful termination of the observable sequence. - parameter onDisposed: Action to invoke upon any type of termination of sequence (if the sequence has gracefully completed, errored, or if the generation is canceled by disposing subscription). - returns: Subscription object used to unsubscribe from the observable sequence. */ publicfuncsubscribe( onNext: ((Element) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onDisposed: (() -> Void)? = nil ) -> Disposable { let disposable: Disposable iflet disposed = onDisposed { disposable = Disposables.create(with: disposed) } else { disposable = Disposables.create() } #ifDEBUG let synchronizationTracker = SynchronizationTracker() #endif let callStack = Hooks.recordCallStackOnError ? Hooks.customCaptureSubscriptionCallstack() : [] ///以下重点关注的代码 创建匿名观察者 let observer = AnonymousObserver<Element> { event in #ifDEBUG synchronizationTracker.register(synchronizationErrorMessage: .default) defer { synchronizationTracker.unregister() } #endif switch event { case .next(let value): onNext?(value) case .error(let error): iflet onError = onError { onError(error) } else { Hooks.defaultErrorHandler(callStack, error) } disposable.dispose() case .completed: onCompleted?() disposable.dispose() } } returnDisposables.create( self.asObservable().subscribe(observer), disposable ) } }
extensionDisposables{ /// Constructs a new disposable with the given action used for disposal. /// /// - parameter dispose: Disposal action which will be run upon calling `dispose`. publicstaticfunccreate(with dispose: @escaping () -> Void) -> Cancelable { AnonymousDisposable(disposeAction: dispose) }
/// When dispose method is called, disposal action will be dereferenced. privatefinalclassAnonymousDisposable : DisposeBase, Cancelable{ // Non-deprecated version of the constructor, used by `Disposables.create(with:)` fileprivateinit(disposeAction: @escaping DisposeAction) { self.disposeAction = disposeAction super.init() } /// Calls the disposal action if and only if the current instance hasn't been disposed yet. /// /// After invoking disposal action, disposal action will be dereferenced. ///销毁核心的逻辑 fileprivatefuncdispose() { if fetchOr(self.disposed, 1) == 0 { iflet action = self.disposeAction { self.disposeAction = nil action() } } } }
void main() { runApp( /// Providers are above [MyApp] instead of inside it, so that tests /// can use [MyApp] while mocking the providers MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => Counter()), ], child: const MyApp(), ), ); }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Example'), ), body: Center( child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: const <Widget>[ Text('You have pushed the button this many times:'),
/// Extracted as a separate widget for performance optimization. /// As a separate widget, it will rebuild independently from [MyHomePage]. /// /// This is totally optional (and rarely needed). /// Similarly, we could also use [Consumer] or [Selector]. Consume<Counter>( builder:(BuildContext context,Counter value,Widget child){ return Text('${value.count}') }, ), Count(), ], ), ), floatingActionButton: FloatingActionButton( key: const Key('increment_floatingActionButton'),
/// Calls `context.read` instead of `context.watch` so that it does not rebuild /// when [Counter] changes. onPressed: () => context.read<Counter>().increment(), tooltip: 'Increment', child: const Icon(Icons.add), ), ); } }
class_ListenerEntryextendsLinkedListEntry<_ListenerEntry> { _ListenerEntry(this.listener); final VoidCallback listener;//真正的监听者 } /// A class that can be extended or mixed in that provides a change notification /// API using [VoidCallback] for notifications. /// /// It is O(1) for adding listeners and O(N) for removing listeners and dispatching /// notifications (where N is the number of listeners). /// /// See also: /// /// * [ValueNotifier], which is a [ChangeNotifier] that wraps a single value. classChangeNotifierimplementsListenable{ LinkedList<_ListenerEntry>? _listeners = LinkedList<_ListenerEntry>();
bool _debugAssertNotDisposed() { assert(() { if (_listeners == null) { throw FlutterError( 'A $runtimeType was used after being disposed.\n' 'Once you have called dispose() on a $runtimeType, it can no longer be used.' ); } returntrue; }()); returntrue; }
/// Whether any listeners are currently registered. /// /// Clients should not depend on this value for their behavior, because having /// one listener's logic change when another listener happens to start or stop /// listening will lead to extremely hard-to-track bugs. Subclasses might use /// this information to determine whether to do any work when there are no /// listeners, however; for example, resuming a [Stream] when a listener is /// added and pausing it when a listener is removed. /// /// Typically this is used by overriding [addListener], checking if /// [hasListeners] is false before calling `super.addListener()`, and if so, /// starting whatever work is needed to determine when to call /// [notifyListeners]; and similarly, by overriding [removeListener], checking /// if [hasListeners] is false after calling `super.removeListener()`, and if /// so, stopping that same work. @protected boolget hasListeners { assert(_debugAssertNotDisposed()); return _listeners!.isNotEmpty; }
/// Register a closure to be called when the object changes. /// /// This method must not be called after [dispose] has been called. @override void addListener(VoidCallback listener) { assert(_debugAssertNotDisposed()); _listeners!.add(_ListenerEntry(listener)); }
/// Remove a previously registered closure from the list of closures that are /// notified when the object changes. /// /// If the given listener is not registered, the call is ignored. /// /// This method must not be called after [dispose] has been called. /// /// If a listener had been added twice, and is removed once during an /// iteration (i.e. in response to a notification), it will still be called /// again. If, on the other hand, it is removed as many times as it was /// registered, then it will no longer be called. This odd behavior is the /// result of the [ChangeNotifier] not being able to determine which listener /// is being removed, since they are identical, and therefore conservatively /// still calling all the listeners when it knows that any are still /// registered. /// /// This surprising behavior can be unexpectedly observed when registering a /// listener on two separate objects which are both forwarding all /// registrations to a common upstream object. @override void removeListener(VoidCallback listener) { assert(_debugAssertNotDisposed()); for (final _ListenerEntry entry in _listeners!) { if (entry.listener == listener) { entry.unlink(); return; } } }
/// Discards any resources used by the object. After this is called, the /// object is not in a usable state and should be discarded (calls to /// [addListener] and [removeListener] will throw after the object is /// disposed). /// /// This method should only be called by the object's owner. @mustCallSuper void dispose() { assert(_debugAssertNotDisposed()); _listeners = null; }
/// Call all the registered listeners. /// /// Call this method whenever the object changes, to notify any clients the /// object may have changed. Listeners that are added during this iteration /// will not be visited. Listeners that are removed during this iteration will /// not be visited after they are removed. /// /// Exceptions thrown by listeners will be caught and reported using /// [FlutterError.reportError]. /// /// This method must not be called after [dispose] has been called. /// /// Surprising behavior can result when reentrantly removing a listener (i.e. /// in response to a notification) that has been registered multiple times. /// See the discussion at [removeListener]. @protected @visibleForTesting void notifyListeners() { assert(_debugAssertNotDisposed()); if (_listeners!.isEmpty) return;
/// A generic implementation of an [InheritedWidget]. /// /// Any descendant of this widget can obtain `value` using [Provider.of]. /// /// Do not use this class directly unless you are creating a custom "Provider". /// Instead use [Provider] class, which wraps [InheritedProvider]. /// /// See also: /// /// - [DeferredInheritedProvider], a variant of this object where the provided /// object and the created object are two different entity. classInheritedProvider<T> extendsSingleChildStatelessWidget{ /// Creates a value, then expose it to its descendants. /// /// The value will be disposed of when [InheritedProvider] is removed from /// the widget tree. InheritedProvider({ Key key, Create<T> create, T Function(BuildContext context, T value) update, UpdateShouldNotify<T> updateShouldNotify, voidFunction(T value) debugCheckInvalidValueType, StartListening<T> startListening, Dispose<T> dispose, this.builder, bool lazy, Widget child, }) : _lazy = lazy, _delegate = _CreateInheritedProvider( create: create, update: update, updateShouldNotify: updateShouldNotify, debugCheckInvalidValueType: debugCheckInvalidValueType, startListening: startListening, dispose: dispose, ), super(key: key, child: child);
/// Syntax sugar for obtaining a [BuildContext] that can read the provider /// created. /// /// This code: /// /// ```dart /// Provider<int>( /// create: (context) => 42, /// builder: (context, child) { /// final value = context.watch<int>(); /// return Text('$value'); /// } /// ) ///
/// /// is strictly equivalent to: /// /// dart
/// Provider<int>(
/// create: (context) => 42,
/// child: Builder(
/// builder: (context) {
/// final value = context.watch<int>();
/// return Text('$value');
/// },
/// ),
/// )
/// /// /// For an explanation on the child parameter that builder receives, /// see the “Performance optimizations” section of [AnimatedBuilder]. final TransitionBuilder builder;
* T Function(BuildContext context, T value) update,该函数返回数据变更值value,具体实现在\_CreateInheritedProvider类中,说白了InheritedProvider\<T>是无状态的,他要变更的话依赖于\_CreateInheritedProvider类,\_CreateInheritedProvider是\_Delegate的实现类,\_Delegate是一个状态代理类,来看一下\_Delegate的实现
```dart @immutable abstract class _Delegate<T> { _DelegateState<T, _Delegate<T>> createState(); void debugFillProperties(DiagnosticPropertiesBuilder properties) {} } abstract class _DelegateState<T, D extends _Delegate<T>> { _InheritedProviderScopeElement<T> element; T get value; D get delegate => element.widget.owner._delegate as D; bool get hasValue; bool debugSetInheritedLock(bool value) { return element._debugSetInheritedLock(value); } bool willUpdateDelegate(D newDelegate) => false; void dispose() {} void debugFillProperties(DiagnosticPropertiesBuilder properties) {} void build({@required bool isBuildFromExternalSources}) {} }
_InheritedProviderScope唯一特殊的地方,我们发现它自己创建了一个Element实现通过覆盖createElement函数,返回_InheritedProviderScopeElement实例,flutter三板斧Widget、Element、RenderObject,该框架自己实现一层Element,我们知道Widget是配置文件,只有build和rebuild以及remove from the tree,而Element作为一层虚拟Dom,主要负责优化,优化页面刷新的逻辑,我们详细看有一下_InheritedProviderScopeElement的源码:
@override void notifyDependent(InheritedWidget oldWidget, Element dependent) { final dependencies = getDependencies(dependent);
var shouldNotify = false; if (dependencies != null) { if (dependencies is _Dependency<T>) { // select can never be used inside `didChangeDependencies`, so if the // dependent is already marked as needed build, there is no point // in executing the selectors. if (dependent.dirty) { return; }
@override void update(_InheritedProviderScope<T> newWidget) { assert(() { if (widget.owner._delegate.runtimeType != newWidget.owner._delegate.runtimeType) { throw StateError(''' Rebuilt $widget using a different constructor. This is likely a mistake and is unsupported. If you're in this situation, consider passing a `key` unique to each individual constructor. '''); } returntrue; }());
@override Widget build() { if (widget.owner._lazy == false) { value; // this will force the value to be computed. } _delegateState.build( isBuildFromExternalSources: _isBuildFromExternalSources, ); _isBuildFromExternalSources = false; if (_shouldNotifyDependents) { _shouldNotifyDependents = false; notifyClients(widget); } returnsuper.build(); }
@override InheritedWidget dependOnInheritedElement( InheritedElement ancestor, { Object aspect, }) { assert(() { if (_debugInheritLocked) { throw FlutterError.fromParts( <DiagnosticsNode>[ ErrorSummary( 'Tried to listen to an InheritedWidget ' 'in a life-cycle that will never be called again.', ), ErrorDescription(''' This error typically happens when calling Provider.of with `listen` to `true`, in a situation where listening to the provider doesn't make sense, such as: - initState of a StatefulWidget - the "create" callback of a provider This is undesired because these life-cycles are called only once in the lifetime of a widget. As such, while `listen` is `true`, the widget has no mean to handle the update scenario. To fix, consider: - passing `listen: false` to `Provider.of` - use a life-cycle that handles updates (like didChangeDependencies) - use a provider that handles updates (like ProxyProvider). '''), ], ); } returntrue; }()); returnsuper.dependOnInheritedElement(ancestor, aspect: aspect); }
abstractclassProxyElementextendsComponentElement{ /// Initializes fields for subclasses. ProxyElement(ProxyWidget widget) : super(widget); @override ProxyWidget get widget => super.widget as ProxyWidget; @override Widget build() => widget.child; @override void update(ProxyWidget newWidget) { final ProxyWidget oldWidget = widget; assert(widget != null); assert(widget != newWidget); super.update(newWidget); assert(widget == newWidget); updated(oldWidget); _dirty = true; rebuild(); } /// Called during build when the [widget] has changed. /// /// By default, calls [notifyClients]. Subclasses may override this method to /// avoid calling [notifyClients] unnecessarily (e.g. if the old and new /// widgets are equivalent). @protected void updated(covariant ProxyWidget oldWidget) { notifyClients(oldWidget); }
abstractclassInheritedContext<T> extendsBuildContext{ /// The current value exposed by [InheritedProvider]. /// /// This property is lazy loaded, and reading it the first time may trigger /// some side-effects such as creating a [T] instance or start a subscription. T get value;
/// Marks the [InheritedProvider] as needing to update dependents. /// /// This bypass [InheritedWidget.updateShouldNotify] and will force widgets /// that depends on [T] to rebuild. void markNeedsNotifyDependents();
/// Wether `setState` was called at least once or not. /// /// It can be used by [DeferredStartListening] to differentiate between the /// very first listening, and a rebuild after `controller` changed. boolget hasValue; }
/// {@template provider.consumer.builder} /// Build a widget tree based on the value from a [Provider<T>]. /// /// Must not be `null`. /// {@endtemplate} final Widget Function(BuildContext context, T value, Widget child) builder;
// 调用_inheritedElementOf函数 static T of<T>(BuildContext context, {bool listen = true}) { assert(context != null); assert( context.owner.debugBuilding || listen == false || debugIsInInheritedProviderUpdate, ''' Tried to listen to a value exposed with provider, from outside of the widget tree. This is likely caused by an event handler (like a button's onPressed) that called Provider.of without passing `listen: false`. To fix, write: Provider.of<$T>(context, listen: false); It is unsupported because may pointlessly rebuild the widget associated to the event handler, when the widget tree doesn't care about the value. The context used was: $context ''', );
final inheritedElement = _inheritedElementOf<T>(context);
if (listen) { context.dependOnInheritedElement(inheritedElement); }
return inheritedElement.value; }
static _InheritedProviderScopeElement<T> _inheritedElementOf<T>( BuildContext context, ) { assert(context != null, ''' Tried to call context.read/watch/select or similar on a `context` that is null. This can happen if you used the context of a StatefulWidget and that StatefulWidget was disposed. '''); assert( _debugIsSelecting == false, 'Cannot call context.read/watch/select inside the callback of a context.select', ); assert( T != dynamic, ''' Tried to call Provider.of<dynamic>. This is likely a mistake and is therefore unsupported. If you want to expose a variable that can be anything, consider changing `dynamic` to `Object` instead. ''', ); _InheritedProviderScopeElement<T> inheritedElement;
if (context.widget is _InheritedProviderScope<T>) { // An InheritedProvider<T>'s update tries to obtain a parent provider of // the same type. context.visitAncestorElements((parent) { inheritedElement = parent.getElementForInheritedWidgetOfExactType< _InheritedProviderScope<T>>() as _InheritedProviderScopeElement<T>; returnfalse; }); } else { inheritedElement = context.getElementForInheritedWidgetOfExactType< _InheritedProviderScope<T>>() as _InheritedProviderScopeElement<T>; } if (inheritedElement == null) { throw ProviderNotFoundException(T, context.widget.runtimeType); } return inheritedElement; }
static T of<T>(BuildContext context, {bool listen = true}) { assert(context != null); assert( context.owner.debugBuilding || listen == false || debugIsInInheritedProviderUpdate, ''' Tried to listen to a value exposed with provider, from outside of the widget tree. This is likely caused by an event handler (like a button's onPressed) that called Provider.of without passing `listen: false`. To fix, write: Provider.of<$T>(context, listen: false); It is unsupported because may pointlessly rebuild the widget associated to the event handler, when the widget tree doesn't care about the value. The context used was: $context ''', );
final inheritedElement = _inheritedElementOf<T>(context);
if (listen) { context.dependOnInheritedElement(inheritedElement); } return inheritedElement.value; }
InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object aspect }); /// Obtains the nearest widget of the given type, which must be the type of a /// concrete [InheritedWidget] subclass, and registers this build context with /// that widget such that when that widget changes (or a new widget of that /// type is introduced, or the widget goes away), this build context is /// rebuilt so that it can obtain new values from that widget. /// /// This method is deprecated. Please use [dependOnInheritedWidgetOfExactType] instead. // TODO(a14n): Remove this when it goes to stable, https://github.com/flutter/flutter/pull/44189 @Deprecated( 'Use dependOnInheritedWidgetOfExactType instead. ' 'This feature was deprecated after v1.12.1.' )
@override void notifyDependent(InheritedWidget oldWidget, Element dependent) { final dependencies = getDependencies(dependent); var shouldNotify = false; if (dependencies != null) { if (dependencies is _Dependency<T>) { // select can never be used inside `didChangeDependencies`, so if the // dependent is already marked as needed build, there is no point // in executing the selectors. if (dependent.dirty) { return; } for (final updateShouldNotify in dependencies.selectors) { try { assert(() { _debugIsSelecting = true; returntrue; }()); shouldNotify = updateShouldNotify(value); } finally { assert(() { _debugIsSelecting = false; returntrue; }()); } if (shouldNotify) { break; } } } else { shouldNotify = true; } } if (shouldNotify) { dependent.didChangeDependencies(); } }
在这个函数里面,构造block的时候把num传了进去,而且是普通值传递,这样的话其实是拷贝了一份num。然后在执行block方法的时候,使用的是拷贝的那份num,从int num = __cself->num; // bound by copy可以看出。这个block也是_NSConcreteStackBlock类型的。
POSIX Threads, usually referred to as pthreads, is an execution model that exists independently from a language, as well as a parallel execution model. It allows a program to control multiple different flows of work that overlap in time. Each flow of work is referred to as a thread, and creation and control over these flows is achieved by making calls to the POSIX Threads API.
– POSIX Threads, Wikipedia
译:
POSIX(Portable Operating System Interface of UNIX,可移植操作系统接口)线程,即 pthreads,是一种不依赖于语言的执行模型,也称作并行(Parallel)执行模型。其允许一个程序控制多个时间重叠的不同工作流。每个工作流即为一个线程,通过调用 POSIX 线程 API 创建并控制这些流。
Threads are a relatively lightweight way to implement multiple paths of execution inside of an application.
【译】线程是在应用程序内部实现多个执行路径的相对轻量的方法。
From a technical standpoint, a thread is a combination of the kernel-level and application-level data structures needed to manage the execution of code. The kernel-level structures coordinate the dispatching of events to the thread and the preemptive scheduling of the thread on one of the available cores. The application-level structures include the call stack for storing function calls and the structures the application needs to manage and manipulate the thread’s attributes and state.
Operation Objects: 任务对象(NSOpeartion)是 OS X 10.5 推出的一个特性。通过封装在子线程执行的任务,隐藏底层的线程管理的具体细节,让开发者聚焦于任务执行的本身。通常来说任务对象会与任务对象队列(NSOperationQueue)结合使用,来实现在一个或多个线程上任务的执行。
GCD: OS 10.6 正式推出,GCD 是另外一种可以让开发者无需知道线程细节而专注于任务本身的一项技术。通过使用 GCD,你可以定义你需要执行的任务,然后把这个任务加入到一个队列中来让 GCD 选择在一个合适的线程上执行这个任务。队列考虑了可用核心的数量和当前负载,这样与直接使用线程相比可以更有效地执行任务。
Whereas a notification center distributes notifications when posted, notifications placed into the queue can be delayed until the end of the current pass through the run loop or until the run loop is idle. Duplicate notifications can be coalesced so that only one notification is sent although multiple notifications are posted.
A notification queue maintains notifications in first in, first out (FIFO) order. When a notification moves to the front of the queue, the queue posts it to the notification center, which in turn dispatches the notification to all objects registered as observers.
Every thread has a default notification queue, which is associated with the default notification center for the process. You can create your own notification queues and have multiple queues per center and thread.
A run loop is a piece of infrastructure used to manage events arriving asynchronously on a thread. A run loop works by monitoring one or more event sources for the thread. As events arrive, the system wakes up the thread and dispatches the events to the run loop, which then dispatches them to the handlers you specify. If no events are present and ready to be handled, the run loop puts the thread to sleep.
You are not required to use a run loop with any threads you create but doing so can provide a better experience for the user. Run loops make it possible to create long-lived threads that use a minimal amount of resources. Because a run loop puts its thread to sleep when there is nothing to do, it eliminates the need for polling, which wastes CPU cycles and prevents the processor itself from sleeping and saving power.
【译】你不需要对你所创建的线程使用运行循环,但是使用运行循环可以提高用户体验。运行循环可以创建使用最少资源的常驻线程。因为当没事做的时候,运行循环会让线程休眠,这样就不许需要通过轮询这种需要消耗 CPU 的低效操作从而节能。
To configure a run loop, all you have to do is launch your thread, get a reference to the run loop object, install your event handlers, and tell the run loop to run. The infrastructure provided by OS X handles the configuration of the main thread’s run loop for you automatically. If you plan to create long-lived secondary threads, however, you must configure the run loop for those threads yourself.
【译】要配置运行循环,你要做的就是启动线程,获取运行循环对象的引用,安装事件处理程序,并告诉运行循环运行。 OS X 提供的基础结构会自动为你处理主线程运行循环的。但是,如果计划创建寿命长的辅助线程,则必须自己为这些线程配置运行循环。
OS X 和 iOS 通过其他 API 为并发提供隐式支持。与其自己创建一个线程,不如考虑使用异步 API,GCD 或操作对象来完成工作。这些技术可以在底层为您完成与线程相关的工作,并且可以保证正确进行。此外,GCD 和操作对象等技术旨在根据当前系统负载调整活动线程的数量,从而比您自己的代码更有效地管理线程。
OS X 和 iOS 为使用 POSIX 线程 API 创建线程提供了基于 C 的支持。这种技术实际上可以用于任何类型的应用程序(包括 Cocoa 和 Cocoa Touch 应用程序),如果您为多个平台编写软件,则可能更方便。用于创建线程的 POSIX 例程被适当地调用为 pthread_create。
It is generally a good idea to leave the priorities of your threads at their default values. Increasing the priorities of some threads also increases the likelihood of starvation among lower-priority threads. If your application contains high-priority and low-priority threads that must interact with each other, the starvation of lower-priority threads may block other threads and create performance bottlenecks
- (void)myThreadMainRoutine { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Top-level pool // Do thread work here. [pool release]; // Release the objects in the pool. }