在讲解Signal类之前,先复习一下dispatch的用法。 1、View层调用自身的dispatch(view)告知绑定的Mediator层也调用自身的dispatch(mediator) 2、Mediator层的dispatch(mediator)通常绑定了两个方法,一个是写在mediator层中的方法(多半是获取数据将数据传给view层,view层再调用自身的方法),一个是在Context中绑定的Command事件,执行顺序是先执行绑定的事件,相关的事件执行完毕返回数据,然后再执行另一个方法(这里比较绕,下面有例子详解)。 3、执行绑定的Command事件,CommadEvent调用自身的方法,此时会调用服务层(Service)的方法,并且在Command自身中给service的dispatch(Service)绑定方法,用于service完成与外界的数据交互调用。 4、Service完成与外界交互,将数据传给CommandEvent。 5、CommandEvent调用之前Service中dispatch(Service)绑定的方法,将数据传给Mediator。 6、Mediator调用dispatch(Mediator)绑定的方法,拿到CommandEvent传过来的数据,调用view层相关方法。 是不是看完上面的步骤感觉头晕,接下来通过一个例子讲解。 现在View层需要一个List类型的数据,但是View不关心如何拿到数据,它只要告诉Mediator层即可。 1、于是,View用自己的dispatch发出了信号。 2、在Mediator层中,View的dispatch有绑定的方法,会通知Mediator执行自己dispatch绑定的事件,并且拿到数据之后执行view层的方法。
需要注意的是,Service也是需要在Context中绑定的 Service拿到数据后通过dispatch的方法传给CommandEvent,CommandEvent再调用自身的dispatch传给Mediator,Mediator拿到数据执行dispatch绑定的view的方法。 举一个不恰当的例子,可以将StrangeIOC理解为寻物接力跑,View把接力棒(dispatch)交给Mediator,Mediator再交给CommandEvent,CommandEvent再交给Service,Service拿到接力棒后开始寻找物体,找到之后再往回跑交给CommandEvent,CommandEvent再给Mediator,最后交到View手中。
复习完之前的内容,现在我们来讲解一下Signal类的用法。 首先第一步,先在Context文件中拷贝以下代码,解除原有的IDispatcher用法,绑定新的signal用法
protected override void addCoreComponents() { base.addCoreComponents(); injectionBinder.Unbind<ICommandBinder>(); injectionBinder.Bind<ICommandBinder>().To<SignalCommandBinder>().ToSingleton(); }
实现一个简单的需求,和原来一样,view层发出一个信号,然后拿到数据进行相应的操作,至于如何拿到数据不管,交给其他几个层解决。 view层代码:
public class Demo1View : View { public Signal RequestSolutionSignal = new Signal(); public void Init() { RequestSolutionSignal.Dispatch(); } public void Load() { Debug.Log("数据已拿到,准备开始加载"); } }
mediator层代码:
public class Demo1Mediator : Mediator { [Inject] public Demo1View demo1View { get; set; } [Inject] public RequestSolutionData requestSolutionData { get; set; } [Inject] public ResponseSolutionData loadSolutionData { get; set; } public override void OnRegister() { demo1View.RequestSolutionSignal.AddListener(() => requestSolutionData.Dispatch()); loadSolutionData.AddListener(demo1View.Load); demo1View.Init(); } }
server层代码
public interface IServices { void LoadData(Action action); }
public class Services : IServices { public void LoadData(Action action) { DataHelper.data = "通过signal信号调用了server层"; Debug.Log("server层已经拿到数据"); action(); } }
Controller层代码:
public class RequestItemsCommand :Command { [Inject] public IServices services { get; set; } [Inject] public ResponseSolutionData loadSolutionData { get; set; } public override void Execute() { Retain(); services.LoadData(loadSolutionData.Dispatch); } }
Signal类:只负责声明信号,不负责实现
//请求远端数据 public class RequestSolutionData : Signal { } //订单数据加载完成,之后开始加载 public class ResponseSolutionData : Signal { }
与Dispatcher用法比起来,Signal类用起来更自由,首先他是根据每一个信号来调用相关方法,不像Disptacher方法是枚举或者字符串,Signal只需要声明一个新的signal继承signal即可。 拿上述demo举例。 view层有一个signal。用来传递获取数据的信息。(即告诉mediator,喂,我要数据) mediator层,有两个signal,一个signal用来与controller层交互,即当view发出要消息的signal时,调用自身的与controller交互的signal让controller去获取数据。另一个signal通知view层,我拿到数据啦,你可以执行相应的方法了。 Controller层有一个signal,Controller接收到信号后,会调用自己的server相对应的方法,完成后调用signal,告诉mediator我拿到数据了,你可以执行相关的方法了。 如果想传递参数,对相应的signal做调整即可。 View层: Mediator层: 声明的Signal做出改变: controller添加对应的参数。 server层方法也添加相应的参数。
测试。
至此。Signal类的简单用法就总结的差不多了,因为工作中拿到接口是对静态变量赋值(很多地方都会用到这个变量),这里演示也是用静态变量,如果想对参数赋值,也可以参考传参的方式自己写一下。 注意点:Mediator要注意各个signal绑定的顺序,不要出现先执行后绑定的情况。调用view层的signal需要单独绑定并实现(即Mediator层和Controller都有的signal)。 不然会报错。
总结的可能有点绕,确实是第一次接触框架,自身硬实力不够,用法也是依葫芦画瓢,希望有一天自己可以成长到能看懂底层代码。 案例Demo(Demo是包含传参的,如果不需要,参照上面代码修改,或者直接删除所有参数即可)