Reactive UI -- 反应式编程UI框架入门学习(一)

这篇具有很好参考价值的文章主要介绍了Reactive UI -- 反应式编程UI框架入门学习(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

反应式编程

反应式编程是一种相对于命令式的编程范式,由函数式的组合声明来构建异步数据流。要理解这个概念,可以简单的借助Excel中的单元格函数。

 

reactiveui,ui,学习,wpf

上图中,A1=B1+C1,无论B1和C1中的数据怎么变化,A1中的值都会自动变化,这其中就蕴含了反应式/响应式编程的思想。

反应式编程对于数据的处理不关心具体的数据值是多少,只要构建出数据的函数式处理,就能并行的异步处理数据流。

Reactive UI

Reactive UI 是一种反应式编程的跨平台MVVM框架,支持Xamarin Forms、Xamarin.iOS、Xamarin.Android、Xamarin.Mac、Tizen、Windows Forms、WPF 和UWP。

本文对比经典的MVVM框架MVVMLight框架来展示ReactiveUI框架的特殊之处。

在MVVMLight中,依赖属性和命令的绑定一般都是放在Xaml中,并且大部分情况下不需要给控件定义Name属性。

1

<Button Content="{Binding Content}" Command="{Binding OpenFileCommand}"/>

这是属于弱绑定,在Reactive UI框架中也提供这样的弱绑定,但Reactive UI框架官方推荐使用后台强绑定方式。

在强绑定方式中,需要给控件定义他的Name属性。

1

<Button Name="btnOpenFile"/>

在界面后台的cs文件中使用强绑定方式。

1

2

//BtnContent是ViewModel中的属性,btnOpenFile是界面中的控件,并指定控件需要绑定的依赖属性

 this.OneWayBind(ViewModel, vm => vm.BtnContent, vw => vw.btnOpenFile.Content);

 在Reactive UI框架中,提供了单向绑定和双向绑定两种绑定类型,上述代码中的OneWayBind是属于ViewModel->View的单向绑定,另外还有一个API  Bind则是双向绑定。

this.Bind(ViewModel, vm => vm.BtnContent, vw => vw.btnOpenFile.Content);

之所以官方推荐这样的绑定方式,是因为框架中提供了一个管理ViewModel生命周期的API WhenActivated,解决了Xaml弱绑定方式带来的内存泄露的可能性。

在WhenActivated API的函数回调中进行绑定属性和Command,可以同步跟踪View和对应绑定属性的生命周期,避免发生内存泄露。

   this.WhenActivated(dispos => {
                this.OneWayBind(ViewModel, vm => vm.BtnContent, vw => vw.btnOpenFile.Content).DisposeWith(dispos);
            });

WhenActivated 会在View被激活时同步调用注册的回调函数,注意,在OneWayBind后面新增了一个API调用DisposeWith,他可以确保当界面被销毁时,对应的viewModel及其绑定的属性和命令也会被销毁。

类似的,绑定Commond

reactiveui,ui,学习,wpf

 this.WhenActivated(dispos => {
                this.OneWayBind(ViewModel, vm => vm.BtnContent, vw => vw.btnOpenFile.Content).DisposeWith(dispos);

                 this.BindCommand(ViewModel,
               viewModel => viewModel.OpenPage,
               view => view.openButton)
               .DisposeWith(disposableRegistration);
            });    

reactiveui,ui,学习,wpf

这样的强绑定相比于Xaml中的弱绑定,会有以下的优势:

1.提供了ViewModel的生命周期管理,避免内存泄露。

2.控件和后台属性的对应关系更为直观,提高代码的可阅读性。

当然也有一定的缺陷,会增加代码量,并且增加View和ViewModel的耦合性。

定义属性和命令

在MVVMLight中定义一个带通知的属性和Commond:

reactiveui,ui,学习,wpf

        private string content ;
        public string Content
        {
            get { return content; }
            set
            {
                content = value;
                RaisePropertyChanged(() => Content);
            }
        }

        private RelayCommand openFileCommand = null;
        public RelayCommand OpenFileCommand
        {
            get { return openFileCommand = openFileCommand ?? new RelayCommand(OpenFile); }
        }

reactiveui,ui,学习,wpf

在ReactiveUI中也通成功了类似RaisePropertyChanged和RelayCommand功能的API,RaiseAndSetIfChanged和ReactiveCommand。

reactiveui,ui,学习,wpf

  private string content;
        public string Content
        {
            get { return content; }
            set
            {
                this.RaiseAndSetIfChanged(ref content,value);
            }
        }

        private ReactiveCommand<Unit, Unit> openFileCommand;
        public ReactiveCommand<Unit, Unit> OpenFileCommand
        {
            get { return openFileCommand = openFileCommand ?? ReactiveCommand.Create(() => { }); }
        }

reactiveui,ui,学习,wpf

其中ReactiveCommand的两个Unit,前一个是传入参数,后一个是返回值。ReactiveCommand的定义与MVVMLight大同小异。

但是在ReactiveUI中,还有更简单方便的定义可通知的属性,使用标记[Reactive]。

 [Reactive]
 public string Content { get; set; }

以上代码等价于

reactiveui,ui,学习,wpf

  private string content;
        public string Content
        {
            get { return content; }
            set
            {
                this.RaiseAndSetIfChanged(ref content,value);
            }
        }

reactiveui,ui,学习,wpf

 动态数据集合

在.Net中,带通知功能的数据集合一般使用ObservableCollection,但是这个类存在一个限制,不支持多线程操作元素,只能在主线程中增加或者删除元素。所以在多线程操作ObservableCollection的时候,一般都需要通过Dispatcher或者线程上下文来推送操作到UI线程。

针对这个问题,ReativeUI框架提供了更优雅的操作方式,SourceList,SourceCache, ObservableCollectionExtended,都是线程安全的集合,需要和ReadOnlyObservableCollection一起搭配使用,用于创建可绑定的线程安全的数据集合。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

//这是用于View绑定的数据集合

private readonly ReadOnlyObservableCollection<string> _disks;

 public ReadOnlyObservableCollection<string> Disks => _disks;

//这里的ObservableCollectionExtended和SourceList作用相同,都是与_disks强关联并创

//建副本集合,在操作数据的时候,不直接操作_disks或者Disks,而是对DisksSource或

//DisksSource2进行操作,会自动的同步到_disk集合并更新到绑定的UI,而Disks用于界面绑定。

  public ObservableCollectionExtended<string> DisksSource;

 public SourceList<string> DisksSource2;

//以下代码是将DiskSource和DiskSource2与_disk建立强关联关系的两种方式

  DisksSource = new();

            DisksSource.ToObservableChangeSet()

                .Bind(out _disks)

                .Subscribe();

 DisksSource2 = new SourceList<string>();

 DisksSource2.Connect().Bind(out _disks).Subscribe();

函数式组合声明

以一个读取磁盘文件夹信息的小功能为例。

一般都需要定义一个ObservableCollection的Model集合,在子线程中需要通过Dispatcher操作集合。

reactiveui,ui,学习,wpf

 public ObservableCollection<FolderModel> FolderModels { get; set; }
        private async Task LoadFolderInfoWithSelectedDiskChanged(string diskName)
        {
            await Task.Run(() => {

                var files = Directory.GetDirectories(diskName);
                foreach (var fileName in files)
                {
                    FolderModel folderModel = new FolderModel();
                    DirectoryInfo directoryInfo = new DirectoryInfo(fileName);
                    folderModel.FolderName = directoryInfo.Name;
                    folderModel.CreateTime = directoryInfo.CreationTime;
                    _dispatcher.Invoke(() => {

                        FolderModels.Add(folderModel);
                    });
                }
            });
        }

reactiveui,ui,学习,wpf

而在ReactiveUI 框架中,不需要Dispatcher这个东西,而是需要通过一个辅助类ObservableAsPropertyHelper。

ObservableAsPropertyHelper 是一个简化 IObservable 和 ViewModel 上的属性之间的互操作的类,为一个普通属性/字段和一个IObservable对象之间建立观察者模式的联系。

以上代码可以修改成:

reactiveui,ui,学习,wpf

  //当前选中的磁盘符号,是一个IObservable对象

  [Reactive]
  public string SelectedDisk { get; set; }

//使用ObservableAsPropertyHelper包装
private readonly ObservableAsPropertyHelper<IEnumerable<FolderModel>> _folderModels;
//FolderModels可用于强绑定
public IEnumerable<FolderModel> FolderModels => _folderModels.Value;

//将_folderModels和SelectedDisk建立观察者和被观察者联系,构建函数组合式声明,当SelectedDisk改变时,
//会自动触发所注册的事件并自动给指定的属性FolderModels赋值。

   _folderModels = this.WhenAnyValue(s => s.SelectedDisk)
                .Where(s => !string.IsNullOrWhiteSpace(s))
                .SelectMany(LoadFolderInfoWithSelectedDiskChanged)
                .ObserveOn(RxApp.MainThreadScheduler)
                .ToProperty(this, nameof(FolderModels));//将计算后得到的结果赋值到指定的属性中

private async Task<IEnumerable<FolderModel>> LoadFolderInfoWithSelectedDiskChanged(string diskName)
        {
            List<FolderModel> folderModels = new List<FolderModel>();
            var files = Directory.GetDirectories(diskName);
            foreach (var fileName in files)
            {
                FolderModel folderModel = new FolderModel();
                DirectoryInfo directoryInfo = new DirectoryInfo(fileName);
                folderModel.FolderName = directoryInfo.Name;
                folderModel.CreateTime = directoryInfo.CreationTime;
                folderModels.Add(folderModel);
            }
            //这个方法中不需要操作FolderModels 只需要把结果返回即可
            await Task.CompletedTask;
            return folderModels;
        }

reactiveui,ui,学习,wpf

其中ObservableAsPropertyHelper包装的对象是可以任何对象,而LoadFolderInfoWithSelectedDiskChanged方法必须要带有结果返回的异步方法,这样就构成了函数式声明的异步数据流。

本文列了一些ReactiveUI的简单使用,下一篇会通过一个实例代码进一步学习ReactiveUI框架文章来源地址https://www.toymoban.com/news/detail-781611.html

到了这里,关于Reactive UI -- 反应式编程UI框架入门学习(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue3 使用UI框架reactive数据更新,视图不更新问题

    本篇主要记录两个问题,然而这两个问题又都可以对应同一种解法。废话少说,解决方法在最上面。推荐格式如下: 一定一定要再多包一层,不然就会遇到一些问题。(⊙﹏⊙)虽然这是一句废话。下面的内容过于基础且本篇只记录bug和解法,想要探求为什么的呢,还请自己去

    2024年02月12日
    浏览(35)
  • 【RN】学习使用 Reactive Native内置UI组件

    当把导航处理好后,就可以学习使用ui组件了(两者没有先后关系,个人习惯)。 在 Android 和 iOS 开发中,一个视图是 UI 的基本组成部分:屏幕上的一个小矩形元素、可用于显示文本、图像或响应用户输入。甚至应用程序最小的视觉元素(例如一行文本或一个按钮)也都是各

    2024年02月22日
    浏览(44)
  • Util应用框架 UI 开发快速入门

    本文是Util应用框架 Angular UI 开发快速入门教程. Util 应用框架目前仅支持用于开发管理后台的 UI. 本文介绍了 Util UI 的技术特点和功能支持. Js语言 TypeScript TypeScript 是 微软开发的脚本语言, 扩展了弱类型的 Javascript,提供增强的语法和强类型支持. 为编辑器代码提示和语法错误检

    2024年02月08日
    浏览(42)
  • Android全新UI框架之Jetpack Compose入门基础

    Jetpack Compose是什么 如果有跨端开发经验的同学,理解和学习compose可能没有那么大的压力。简单地说,compose可以让Android的原生开发也可以使用类似rn的jsx的语法来开发 UI界面 。以往,我们开发Android原生页面的时候,通常是在xml中画相关的UI控件,然后在activity中通过findViewB

    2024年02月21日
    浏览(45)
  • Net跨平台UI框架Avalonia入门-安装和使用

    Avalonia UI是是Net的跨平台UI框架,支持 Windows、Linux、iOS 和 Android,与Net其他UI框架相比,如WPF(Windows平台)、MAUI跨平台控件(Android、iOS、macOS 和 Windows),主要优势是支持Linux。在国产化的需求下,对于C#开发的程序员,Avalonia适合用来开发Linux的桌面客户端。 v11版本已经发布

    2024年02月05日
    浏览(87)
  • 响应式编程初探-自定义实现Reactive Streams规范

    最近在学响应式编程,这里先记录下,响应式编程的一些基础内容 Reactive Streams、Reactor、WebFlux以及响应式编程之间存在密切的关系,它们共同构成了在Java生态系统中处理异步和响应式编程的一系列工具和框架。 Reactive Streams: Reactive Streams 是一个规范,定义了一组接口和协议

    2024年02月01日
    浏览(33)
  • Element UI框架学习篇(二)

    1.1 前提说明 1.2 从左往右布局 1.2.1 示例代码 1.2.2 运行截图 1.3 从上往下布局 1.3.1 示例代码 1.3.2 运行截图 1.4 作业练习 1.4.1 通过整体布局完成如下图所示的结构 1.4.2 示例代码 1.4.3 运行截图 2.1 常规显示按钮颜色 2.1.1 核心点 2.1.2 示例代码 2.1.3 运行截图 2.2 悬停显示按钮颜色

    2024年02月12日
    浏览(43)
  • Unity进阶-ui框架学习笔记

    笔记来源课程:https://study.163.com/course/courseMain.htm?courseId=1212756805_trace_c_p_k2_=8c8d7393c43b400d89ae94ab037586fc 最上面的管理层(canvas) 调整下运行顺序,让他快于controller panel的控制层 panel下面的组件层 使用

    2024年02月16日
    浏览(50)
  • Spring Reactive:响应式编程与WebFlux的深度探索

    🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页 ——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍专栏》 🐾 学会IDEA常用操作,工作效率翻倍~💐 🌊 《100天精通Golang(基础

    2024年02月09日
    浏览(43)
  • vue ui 创建项目没有反应

    cmd中输入 vue ui 没有反应 vue ui命令需要vue3.0以上的版本 才可以 1、查看当前版本 vue版本在3.0以下是没有ui命令的 2、查看版本所拥有的命令  3、卸载之前版本的vue 卸载完成,检查是否已经卸载  4、安装@vue/cli  等待安装...... 5、检查是否安装成功,查看版本 查看vue命令中是否

    2024年02月11日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包