我们已经使用Flutter有一段时间了,但是目前我们使用Flutter构建的界面都有一个问题,一旦这个界面切换之后,再次出现时界面状态就会被重置,尤其是底部导航所对应的几个主界面,每次切换都会重新渲染,这样显然是不合适的;那么有没有办法,能够在主界面切换之后,再次切换回来时,依然能够保持之前的状态呢?这就需要使用到Flutter中的混入Mixins

Mixins

Flutter中,Dart是不支持多继承的,但是我们可以通过Mixins给一个类添加功能,通过这种方式实现多继承;接下来,我们以上篇文章中实现的聊天界面来演示一下Mixins的使用;

FlutterMixins并不是操作继承自StatefulWidget的界面,因为我们要保留状态,所以应该操作其对应的State,其通过with关键字实现;

想要实现状态的保留,需要有三步操作:

  • with关键字实现混入;
  • 重写wantKeepAliveget方法,返回true
  • 实现super.build(context)方法;

比如,我们想要实现聊天界面与通讯录界面切换之后,两个界面都能够保持之前的状态,那么我们需要做两方面的工作:

  • 底部导航所在页面的状态保持;
  • 聊天界面你的状态保持

底部导航栏状态保持

我们先来看一下当前底部导航栏切换界面的代码:
image.png
我们是通过Scaffold部件的bottomNavigationBar中的点击事件onTap来切换页面索引,然后通过所以从数组中取出界面,而数组中的界面每一次都是最新的,每一次切换界面都是在做状态的更新(点击方法中调用了setState),那么之前的界面切换之后就会被销毁;

那么想要保持状态不更新,就需要将数组中的界面都放在Widget树中,只控制显示和隐藏;

PageController

我们需要先创建一个PageController

  1. final PageController _pageController = PageController();

我们通过PageController来切换界面;

PageView

接下来,我们将Scaffoldbody使用PageView:
image.png

  • controller:传我们创建的PageController
  • children:传我们存放页面的数组;

这样就能将我们的界面存入Widget树中;

接下来修改我们的onTap方法:
image.png
使用_pageController进行页面切换;但是此时还有一个问题:
Flutter(二十一)-部件状态的保持 - 图4
我们使用了PageControllerPageView之后,页面具备了滑动切换的功能,但是滑动时,底部的状态平没有随着切换;所以在页面改变时,我们还需要同步改变选中的索引,也就是_currentIndex
image.png
效果如下:
Flutter(二十一)-部件状态的保持 - 图6

禁止滑动切换

如果想要禁用滑动切换页面的效果,可以通过PageViewphysics属性:
image.png

聊天界面状态保持

with关键字

我们想要保留聊天界面的状态,那么我们需要将代码修改为:
image.png

  • with使用该关键字试下混入;
  • AutomaticKeepAliveClientMixin保持该页面状态时,需要混入的Mixins
  • ChatPage传入泛型,也就是对应的页面;

    重写wantKeepAlive方法

    我们可以看到,此时_ChatPageState爆出错误;这是因为实现混入功能,我们需要重写wantKeepAlive,代码如下:
    image.png

    wantKeepAlive是一个get方法;

super.build

最后,我们需要在原来的渲染方法build方法中实现super.build(context)
image.png

其他几个页面我们一次按照这三部进行修改,最终效果如下:
Flutter(二十一)-部件状态的保持 - 图11