在讲解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是包含传参的,如果不需要,参照上面代码修改,或者直接删除所有参数即可)