Flutter初体验-02-ui端

前言

上一篇我简要介绍了flutter和app的概况,有兴趣的朋友可以先看一下上一篇:我的Flutter初体验-1CSDN/酷安

之前有朋友提出我的项目接近mvi架构,不过我认为更接近于mvc和mvi的结合:

  • app的页面由三部分组成:view、state和logic(getx常用结构),其中view负责页面展示,state负责存储页面状态,logic负责数据获取、数据处理、状态刷新和页面刷新;
  • 与mvc架构相比,view对应v,而state和logic对应m和c;
  • 与mvi架构相比,view对应v,state和logic对应m和i,虽然状态均保存在state中,但是没有专门的intent层;
  • 所以我的项目既不属于mvc架构,也不属于mvi架构(业余选手的辩词)。

在上一篇中,我将app大体分为了ui端和逻辑端两个部分,下面我将介绍ui端的要点。

ui端

在ui端,我认为主要有状态管理和异步显示两个要点,下面一一进行介绍。

状态管理

ui界面的每个组件都有自己的状态,这些状态包括数据、颜色等,状态管理主要指的是动态组件的状态更新问题。

  1. stateful widget

在flutter中,页面上每个组件都被称作widget,根据组件的状态或数据是否会发生改变,分为stateless widgetstateful widget两种。其中stateless widget的状态和数据不会发生改变,stateful widget的状态和数据可能会发生改变。

若app的某个组件的状态会发生改变,就可以把这个组件定义为stateful widget,同时定义其对应的state,该state专门负责维护此widget的状态。在需要更新组件状态时,调用state的setState方法即可刷新组件状态。

采用这种状态管理方法,一个widget的状态可以由自身管理,也可以交给父widget管理。

  1. getx

除了官方提供的状态管理方法外,也有很多第三方库也提供了状态管理方法,其中,被称为flutter开发神器的getx就提供了GetBuilder响应式两种状态管理方法。

  • GetBuilder
    • GetBuilder是一种简单状态管理方法,在使用时仍需要手动调用方法实现组件刷新;
    • 在使用时,可以将动态组件定义为stateless widget,使用GetBuilder包裹,并指定其对应的controller;
    • 当组件的状态改变时,可以直接对状态变量进行赋值,再在controller中调用update()方法更新组件;
    • 通过分析源码,可以看出,GetBuilder实际上在原有组件外面包裹了一层stateful widget,是对官方状态管理方法的简化。通过GetBuilder,我们可以在同一处管理所有的状态并进行组件刷新,简化了代码复杂度。
  • 响应式
    • 响应式状态管理指的是变量与组件绑定,只要变量发生数据变化,那么组件就会自动刷新,而无需手动调用刷新方法;
    • 在使用时,需要将状态变量定义为响应式变量(getx提供的.obs扩展),并在组件中使用该响应式状态变量的value;
    • 当响应式状态变量的value被重新赋值后,getx就会主动调用组件刷新的方法;
    • 通过分析源码,我认为getx的响应式状态管理实际上采用了观察者模式,在响应式状态变量被赋新值时,就会通知订阅者执行更新操作。

GetBuilder和响应式状态管理都属于全局状态管理方法,即:所有的widget的状态不论层级,均进行统一管理。

我的项目中采用了getx的GetBuilder方法进行状态管理。除了状态管理之外,getx也提供了依赖注入、路由管理等功能的解决方案,大大简化了项目结构,提升了开发效率(不过flutter官方好像不是很喜欢getx)。

异步显示

在我的项目中,扫描、查询等都是耗时操作,为了不影响用户界面,这些耗时操作都需要在后台执行,并异步显示结果。下面将介绍几种我了解到的异步显示方法。

  1. FutureBuilder/StreamBuilder

前文提到,Future和Steam是dart的两种异步编程方式,Future可以返回一个异步操作的结果,而Stream可以返回一系列异步时间的结果,FutureBuilder和StreamBuilder正是基于这两种异步操作构建的异步显示组件。

  • builder是flutter中用来创建widget的函数,FutureBuilder和StreamBuilder的用法和普通widget相同;
  • 在FutureBuilder中,必须定义一个返回值为Future的异步函数,根据该函数的状态返回不同的widget;
  • 在StreamBuilder中,必须定义一个返回值为Steam的异步函数,根据Stream中的事件返回不同的widget;

可以看出,FutureBuilder只能根据异步操作是否执行完毕,返回两种不同的widget;而StreamBuilder则可通过监听一系列事件,返回多种不同的widget,可以实现粒度更细的异步显示。

在ui界面的编写中,FutureBuilder和StreamBuilder完全可以替代普通的widget,在我的项目中,扫描结果的显示正是通过FutureBuilder实现的,若扫描操作尚在执行中,就返回loading界面;若扫描操作执行结束,就返回扫描结果列表,如下图所示:

  • 扫描函数执行中,展示loading界面:
    loading界面

  • 扫描函数执行完毕,展示扫描结果:
    结果界面

上述功能同样可以采用StreamBuilder实现,甚至效果更好!这也是我的一个改进方向。

  1. Future/Stream+手动刷新
    不用官方的提供的组件,我们自己也可以用Future/Stream配合手动刷新实现异步显示。
  • 对于Future来说,只需要在执行结果返回后对状态变量赋值,并刷新组件即可;
  • 对于Stream来说,可以订阅该Stream,并在每次监听到事件时更新数据并刷新组件以实现异步显示。

相对于FutureBuilder和StreamBuilder,我认为Future/Stream+手动刷新的方法更自由,也能够实现更为复杂的功能,比如:可以在不同位置订阅同一个Stream,以便根据同一个异步操作进行多个位置的组件刷新。

剩下的

本来想在这一篇中把ui端和逻辑端都介绍完,但是不知不觉ui端就写了这么多了。因为我不想写太长的文章(懒),所以逻辑端将会在下一篇中介绍。

上面的介绍可能存在错误或者疏漏的地方,请大家批评指正~

最后附上app和项目地址:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值