80 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			80 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
import 'dart:async';
 | 
						|
 | 
						|
import 'package:flutter/foundation.dart';
 | 
						|
 | 
						|
typedef EventCallback<Data> = Future<dynamic> Function(Data data);
 | 
						|
 | 
						|
abstract class BaseEvent<EventType, Data> {
 | 
						|
  EventType type;
 | 
						|
  Data data;
 | 
						|
 | 
						|
  /// Constructor.
 | 
						|
  BaseEvent(this.type, this.data);
 | 
						|
 | 
						|
  /// Consume this event.
 | 
						|
  @visibleForTesting
 | 
						|
  Future<dynamic> consume() async {
 | 
						|
    final cb = findCallback(type);
 | 
						|
    if (cb == null) {
 | 
						|
      return null;
 | 
						|
    } else {
 | 
						|
      return cb(data);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  EventCallback<Data>? findCallback(EventType type);
 | 
						|
}
 | 
						|
 | 
						|
abstract class BaseEventLoop<EventType, Data> {
 | 
						|
  final List<BaseEvent<EventType, Data>> _evts = [];
 | 
						|
  Timer? _timer;
 | 
						|
 | 
						|
  List<BaseEvent<EventType, Data>> get evts => _evts;
 | 
						|
 | 
						|
  Future<void> onReady() async {
 | 
						|
    // Poll every 100ms.
 | 
						|
    _timer = Timer.periodic(Duration(milliseconds: 100), _handleTimer);
 | 
						|
  }
 | 
						|
 | 
						|
  /// An Event is about to be consumed.
 | 
						|
  Future<void> onPreConsume(BaseEvent<EventType, Data> evt) async {}
 | 
						|
  /// An Event was consumed.
 | 
						|
  Future<void> onPostConsume(BaseEvent<EventType, Data> evt) async {}
 | 
						|
  /// Events are all handled and cleared.
 | 
						|
  Future<void> onEventsClear() async {}
 | 
						|
  /// Events start to consume.
 | 
						|
  Future<void> onEventsStartConsuming() async {}
 | 
						|
 | 
						|
  Future<void> _handleTimer(Timer timer) async {
 | 
						|
      if (_evts.isEmpty) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      timer.cancel();
 | 
						|
      _timer = null;
 | 
						|
      // Handle the logic.
 | 
						|
      await onEventsStartConsuming();
 | 
						|
      while (_evts.isNotEmpty) {
 | 
						|
        final evt = _evts.first;
 | 
						|
        _evts.remove(evt);
 | 
						|
        await onPreConsume(evt);
 | 
						|
        await evt.consume();
 | 
						|
        await onPostConsume(evt);
 | 
						|
      }
 | 
						|
      await onEventsClear();
 | 
						|
      // Now events are all processed.
 | 
						|
      _timer = Timer.periodic(Duration(milliseconds: 100), _handleTimer);
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> close() async {
 | 
						|
    _timer?.cancel();
 | 
						|
  }
 | 
						|
 | 
						|
  void pushEvent(BaseEvent<EventType, Data> evt) {
 | 
						|
    _evts.add(evt);
 | 
						|
  }
 | 
						|
 | 
						|
  void clear() {
 | 
						|
    _evts.clear();
 | 
						|
  }
 | 
						|
}
 |