rx文件管理器window_使用ReactiveX/Rx.NET给UI编程模型解耦

8e034cb938981214f4d2d91e0dca5e08.png

Window软件UI编程的时候,时常会有些代码,为了去Update UI的变化,总是会写出逻辑不是很干净的代码。假如下面的逻辑
1.选择一个文本文件
2.逐行读取插入一个listbox
3.同时更新一个插入进度条progressbar
如果从经典的MVC架构角度来考虑这个问题,UI部分可以视作是View。而View的更新也就是两种方法,pull或者push。最简单的办法就是push。也就是上面的逻辑顺序,主动的同步更新进度条。
一般的写出来的代码就是如此样子:

  string file = this.openFileDialog1.FileName;
  this.textBox1.Text = file;
  this.texts = File.ReadAllLines(file);
  this.progressBar1.Maximum = this.texts.Length;
  foreach (var item in this.texts)
  {
       this.listBox1.Items.Add(item);
       this.progressBar1.Step = this.listBox1.Items.Count;
       this.progressBar1.PerformStep();
   }


但这样的写法,在主逻辑中需要插入了两条控制UI Update的代码:

 this.progressBar1.Step = this.listBox1.Items.Count;
 this.progressBar1.PerformStep();


这两行代码,让原本逻辑和功能清楚的代码逻辑突然变得有点乱了。现在让我们回顾下,我们的核心目的是读取文件,并插入listbox。原本的代码应该是:

  string file = this.openFileDialog1.FileName;
  this.textBox1.Text = file;
  this.texts = File.ReadAllLines(file);
  foreach (var item in this.texts)
 {
      this.listBox1.Items.Add(item);
  }

可是为了增加UI的友好度,增加了一个进度条。只能在里面插入操作进度条的代码,于是变成了本文开头的例子,一份混乱的耦合代码。成了混合着核心逻辑和更新UI的代码。如果要同时更新多个UI元素呢,比如一个Label?再增加两行更新UI的代码吗?慢慢的代码就会变的越来越混乱不堪了。这些代码本身没错,也运行良好,但是能不能写出更加干净的代码呢?答案是能:不是Pull模式,是观察者模式。
观察者模式的定义是这样的,“让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己”。从这个说明可以很明显的看出,观察者模式是一种解耦模式。回顾我们的第一段例子,逻辑代码和Update 进度条的逻辑耦合在一起,就变得不清爽了。我们现在要做的就是用观察者模式把逻辑和更新进度条的功能分开。
先上一小段代码。

//进度条代码,主动观察listbox的状态,更新自己
this.progress_observ = Observable
              .Interval(TimeSpan.FromMilliseconds(1000))
              .ObserveOn(this.progressBar1)
              .Subscribe(r =>
              {
                  this.progressBar1.Step = this.listBox1.Items.Count;
                  this.progressBar1.PerformStep();
              });


简单说明下这一行代码的含义:1.定义了一个Observable对象(可观察对象)2.间隔1000毫秒发送一次通知3.针对当前UI控件来设置调度器,这个调度器主要是确保下面的订阅代码在UI线程上执行4.得到通知之后,更新progressBar1
这行代码的逻辑,实际上自己定义一个Timer也是能实现的。但是为什么要这么做呢?回到前面提出的第二个问题?插入ListBox的同时,要同步更新多个UI元素,该怎么办?更进一步,UI元素随着插入数据量的变化,需要改变字体的颜色呢?随着要做出丰富多彩的的UI设计,就会发现Update UI的逻辑会越来越多,甚至超过核心逻辑本身。那么能不能让UI元素自己决定是不是要更新呢?答案还是观察者模式。具体应用框架是ReactiveX系列框架。
ReactiveX技术框架是一整套的观察者模式的实现,具体实现的语言版本有很多,主流的JAVA,C#,JS,Python都有。这篇文章用的例子代码是http://Rx.NET的实现。简单介绍见文末附加信息。具体的学习和资料,大家可以去参考相关的文档。在这里不做详细说明。
结合起来,解耦效果最好的写法就是

//主逻辑,插入列表,不考虑更新进度条
 string file = this.openFileDialog1.FileName;
  this.textBox1.Text = file;
  this.texts = File.ReadAllLines(file);
  foreach (var item in this.texts)
  {
     this.listBox1.Items.Add(item);
  }



//进度条自动去观察listbox的状态,自动更新自己
this.progress_observ = Observable
              .Interval(TimeSpan.FromMilliseconds(1000))
              .ObserveOn(this.progressBar1)
              .Subscribe(r =>
              {
                   this.progressBar1.Step = this.listBox1.Items.Count;
                   this.progressBar1.PerformStep();
              });


两段代码各行其事。没有任何交集之处。完美解耦。
如果要增加一些UI变化,可以继续增加类似代码

//额外增加一个lable来显示listbox中的数量,不需要改动任何listbox相关代码
//每一秒钟自动更新一次lable数据
Observable.Interval(TimeSpan.FromMilliseconds(1000))
              .ObserveOn(this.label1)
              .Subscribe(r =>
              {
                  this.label1.Text = this.listBox1.Items.Count.ToString();
              });


依然不需要改动任何原先的progress操作的代码和listbox的操作代码,只要继续添加更新UI的代码就可以。毫无历史负担。这只是http://Rx.NET最简单的应用之一,但已经是给UI开发带来了很多新的变化。http://Rx.NET是个好东西,UI的处理只是其中很小一块内容。有更多内容等待发现。

ReactiveX的简单介绍:
这是从中文化文档中摘抄的两段介绍。 https:// mcxiaoke.gitbooks.io/rx docs/content/Intro.html ReactiveX的历史
ReactiveX是Reactive Extensions的缩写,一般简写为Rx,最初是LINQ的一个扩展,由微软的架构师Erik Meijer领导的团队开发,在2012年11月开源,Rx是一个编程模型,目标是提供一致的编程接口,帮助开发者更方便的处理异步数据流,Rx库支持.NET、JavaScript和C++,Rx近几年越来越流行了,现在已经支持几乎全部的流行编程语言了,Rx的大部分语言库由ReactiveX这个组织负责维护,比较流行的有RxJava/RxJS/Rx.NET,社区网站是 reactivex.io。 什么是ReactiveX
微软给的定义是,Rx是一个函数库,让开发者可以利用可观察序列和LINQ风格查询操作符来编写异步和基于事件的程序,使用Rx,开发者可以用Observables表示异步数据流,用LINQ操作符查询异步数据流, 用Schedulers参数化异步数据流的并发处理,Rx可以这样定义:Rx = Observables + LINQ + Schedulers。 http:// ReactiveX.io 给的定义是,Rx是一个使用可观察数据流进行异步编程的编程接口,ReactiveX结合了观察者模式、迭代器模式和函数式编程的精华。

最后推荐一本http://RX.NET的学习书籍《Reactive Programming for .NET Developers》更多信息请关注我的公众号 【技术宅指北】

谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值