准备网络数据
这一步不是很重要,提供一些假数据而已,不是重点嫌麻烦的可以跳过。
先介绍一个网址:点击 这个网址用来搭建我们需要的网络数据,注册账号非常简单,这里就不多说了。
注册完成之后,新建一个仓库,简简单单取个名字就够了:
之后点击进入仓库,可以看到下图:
会默认生成以一个示例接口,可以看一看示例接口的生成规则。看不懂也没关系,我们直接直接上手自己新建一个接口,如图所示:
点击右上角的编辑按钮进入编辑模式,新建一个响应chatlist,类型为Array。然后生成chatlist的数据,imageUrl表示每条聊天数据的用户头像。其中用户头像的初始值里面有一段@natural(20,99),这个是Mock.js代码。这里是相关介绍mockjs.com/
每条聊天数据,除了imageUrl还需要有用户名name和消息的内容message。@cname用来生成随机的中文名,@cparagraph用来生成随机的中文段落来表示聊天内容。我们这里只是简单的构造一下这个聊天列表所需要的数据,真正的聊天列表的数据肯定是不会这么简单的。。。
编辑的差不多的时候,记得点击保存,保存之后点击红圈中的图标就可以获取到数据
聊天页面导航条
准备工作
默认展示页面改为_currentIndex 改为0,新建chat 目录,将相关文件放在这里。
添加加号按钮
加号按钮这个东西,我们之前已经添加过类似的了,appBar 的actions 就是我们需要添加代码的地方。
如果我们按照这个思路写下去的话,就需要自己再去实现一个弹出菜单的类。其实flutter 提供了我们一些现成的类可以做到类似的效果。
PopupMenuButton
PopupMenuButton 类用来弹出一个菜单,必传参数为itemBuilder ,用来实现它需要展示的内容。PopupMenuItem 就是用来展示内容的类。这里有一个细节说一下,PopupMenuButton 有一个onSelected 属性,这个属性是个闭包,意思是选中某个PopupMenuItem 的时候,会调用这个闭包。但是有一个前提就是每个PopupMenuItem 的value 必须不为null的时候,才会执行onSelected 闭包,我在这里卡了半天,网上找了半天资料也没有明确讲到这里。其他就没什么好讲的了,都比较简单。
还有一个小细节,如何设置PopupMenuButton 的颜色,可以直接设置它的颜色
还可以设置APP的主题的cardColor ,不过这个优先级没有直接设置PopupMenuButton 颜色高。
请求网络数据
这个网站可以搜索flutter 使用的包packages 。我们使用http 这个包来请求我们的网络数据。这个包是flutter 官方提供的。实际项目开发的时候可能并不会使用http 这个包,大部分是使用dio 来请求网络数据。这里只介绍官方的http包如何使用。
导入http包
首先作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS开发公众号:编程大鑫,不管你是小白还是大牛都欢迎入驻 ,让我们一起进步,共同发展!(群内会免费提供一些群主收藏的免费学习书籍资料以及整理好的几百道面试题和答案文档!)
粘贴完成之后需要更新一下,就是获取一下包对应的代码。可以通过上方的Pub get ,也可以在终端中输入flutter packages get
命令执行完之后,就可以使用这个包了。
导入http头文件并取别名
发送请求
请求的发送写在initState 里面。getData() 后面跟了一个async 表示的是异步执行。async 需要搭配await 使用,await 后面跟着的是耗时的代码。所以上面的程序会先打印来了,然后再输出请求的状态码;
点击其他的页面,再次回到当前页面会发现initState 方法重新走了一遍,这是因为我们还没有保存住状态,后面会讲到如何保持Widget 的状态。
处理返回的数据
首先介绍一下,在flutter 中如何将请求返回的JSON 数据转为Map ,在我们iOS 开发中是转为字典,而flutter中没有字典这个类型,对应的类型是Map 。以及如果将Map 转为JSON 。在iOS 中我们知道会使用一个NSJSONSerialization 的类用来处理JSON 数据。同样的,在flutter 中也会有一个专门的类JsonCodec 来处理。
JSON和Map互相转
其中的json 就是JsonCodec 的实例。需要导入'dart:convert' 头文件。flutter中 还可以通过is 来判断是不是某个类型。
新建聊天模型
除了红框内的方法之外,其他没什么新鲜事物。红框内的方法应该说是一个工厂方法,是设计模式的一种,用来初始化对象的。除了默认的初始化方法,还可以使用这个工厂方法来实例化一个Chat对象。模型建立好了之后就可以处理响应的数据了
处理响应的数据
这里用到了Future,关于Future的讲解可以看官方文档dart.cn/tutorials/l…
使用FutureBuilder显示界面
很多时候我们会依赖一些异步数据来动态更新UI,比如在打开一个页面时我们需要先从互联网上获取数据,在获取数据的过程中我们显示一个加载框,等获取到数据时我们再渲染页面;当然,通过StatefulWidget 我们完全可以实现上述这些功能。但由于在实际开发中依赖异步数据更新UI的这种场景非常常见,因此Flutter 专门提供了FutureBuilder 来快速实现这种功能。FutureBuilder 会依赖一个future ,它会根据所依赖的future 的状态来动态构建自身。这个future 我们刚刚已经准备好了。关于FutureBuilder 的介绍就不详细介绍了。 最后完整代码如下:
不使用FutureBuilder的方式
刚刚说了,我们可以使用FutureBuilder 来快速实现展示异步网络数据,也可以自己实现,现在我们自己实现一下。使用一个私有变量_chatList 记录请求下来的数据,再根据_chatList 的值来展示不同的页面。代码如下:
因为getData 的返回值是Future 的原因,getData() 后面可以跟then 方法,还可以跟错误捕获catchError ,完成时的回调whenComplete ,超时设置timeOut 等等,这种写法挺有意思,一路点下去就完了…
实现超时取消刷新功能
在每次请求的时候,重置_cancelConnect 的值。
保持Widget的状态
我们来回点击通讯录页面和聊天页面,会发现每次点击进入当前的页面,都会重新的载入,initState() 会被重新调用。将通讯录页面滑动到底部,再次点击进入会发现又默认回到了顶部。为什么会出现这样的问题。正是因为我们的Widget 的状态没有保持,每次展示都重新创建了。
Dart 语言中有一个Mixins 的概念:官方的解释是这样,可以给类A Mixins 一个B,那么A就拥有了B的属性和方法。有点像OC的类扩展的意思。保持Widget 的状态就需要用到这个语言特性。一共有三个步骤:
1.Mixins 类AutomaticKeepAliveClientMixin 2. 重写wantKeepAlive 方法 3. 调用父类Builder 方法
同样把通讯录页面也实现上面的步骤。然后再次来回点击发现还是没有保持住状态???这里有一个最大的问题就是我们的根Widget 都没有保持住状态,那还谈什么保持子Widget 的状态呢。。。
使用PageView
来到rootPage.dart 文件,我们会看到body 里面直接取了数组的某个元素作为根Widget 展示。这样是无法保持住状态的,使用PageView 才可以保持住状态。
使用PageView,代码如下:
点击跳转到其他页面就可以直接通过_pageController 来完成。使用了PageView 之后会发现,不同的页面之间可以直接通过手势左右滑到就能切换了。这样的效果我们一般是不需要的,可以设置直接关闭。如果需要的话,在滑动的方法里面重新设置底部导航条的正确位置也是没有问题的。
使用滑动切换,解决bug
禁用滑动切换
本篇文章就到这里了,感谢观看!
|