为我的Google Visualization API包装器提供可重用流的最佳方法是什么?

时间:2015-05-04 16:48:23

标签: events dart google-visualization dart-async dart-js-interop

我正在为Google Visualization / Charts API开发一个基于Dart的包装器,可以在github处查看。我为所有可用的图表创建了一个特定于图表的包装类。

现在我正在调查基础类的事件。问题是所有图表中都存在的各种事件。因此,我需要找到一种方法将特定事件类型分配给相应的图表。我已经做的是:

  1. 我为Events api创建了一个包装器:

    abstract class Events {
      static JsObject addListener(source_visualization, event_name, Function handling_function) {
        return vis['events'].callMethod('addListener', [source_visualization, event_name, new JsFunction.withThis(handling_function)]);
      }
    
      static JsObject addOneTimeListener(source_visualization, event_name, handling_function(e)) {
        return vis['events'].callMethod('addOneTimeListener', [source_visualization, event_name, new JsFunction.withThis(handling_function)]);
      }
    
      static void removeListener(listener_handler) {
        return vis['events'].callMethod('removeListener', [listener_handler]);
      }
    
      /// TODO(rh): removeAllListeners
    }
    
  2. 我创建了一个wrapper class,它封装了一个事件的所有代码。代码如下所示:

    class EventWrapper<E extends Event> {
      JsObject _jsChart;
      String _eventName;
      JsObject _handler;
      Stream<E> get onEvent => _streamController.stream;
      StreamController<E> _streamController;
      ...
      EventWrapper(this._jsChart, this._eventName, E reviver(p)) {
        _streamController = new StreamController.broadcast(onListen: () => _onListen(_eventName), onCancel: () => _onCancel(_eventName));
      }
    
      void _onListen(String event) {
        _handler = Events.addListener(_jsChart, event, ...);
      }
    
      void _onCancel(String event) {
        Events.removeListener(_handler);
      }
    }
    
  3. 在图表中,您可以使用以下代码:

    class PieChart ... {
      Stream<SelectEvent> get onSelect => _selectEventHandler.onEvent;
      EventWrapper _selectEventHandler;
    
      PieChart(Element e) : super._(e, "PieChart", vis) {
        _selectEventHandler = new EventWrapper<SelectEvent>(jsChart, 'select', (p) => new SelectEvent());
        // Other Events
      }
      // ...
    }
    
  4. 问题是以下Events接口需要source_visulization参数,即我想要注册事件的图表。但是当我使用dart:js时,这仅在我在图表上调用构造函数后才可用,因为这会通过JsObjectjsChart = new JsObject(ctx[chartName], [element]))创建对象。通常我会在构造函数中创建EventWrapper个实例,但由于我必须使用几个类中的事件,我想到了另外两个解决方案,而不是当前在#3上看到的。

    1. 创建一个mixin - 这不起作用,因为我没有构造函数而且我无法指定instsance方法,因为它给了我一个错误:

      abstract class SelectEventMixin {
        Stream<SelectEvent> get onSelect => _selectEventHandler.stream;
        final StreamController _selectEventHandler = new StreamController.broadcast(onListen: _onListen);
      
        void _onListen() {
          // jsChart is available here
        }
      }
      
    2. 为每个看到的事件组合创建BaseClasses,这将允许我共享最常用的代码。一些BaseClasses将是:NoEventsSelectEventSelectReadyEventsSelectReadyAnimationFinishEvents,...

    3. 你们中有谁有更好的解决方案吗?或者有人可以告诉我如何解决我的问题#1? #2已经是最好的解决方案吗?因为我只需要组合几种方法,只有一些重复的代码?

0 个答案:

没有答案