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();
 | |
|   }
 | |
| }
 |