来自:掘金,作者:星星y
链接:https://juejin.im/post/5db9889ae51d4529e8394e63
哎,Flutter真香啊
早在一年前想学习下flutter,但当时对于它布局中地狱式的嵌套有点望而生畏,心想为什么嵌套这么复杂,就没有xml布局方式吗,用jsx方式也行啊,为什么要用dart而不用javascript,走开,劳资不学了。
然而,随着今年google io大会flutter新版本发布,大势宣扬。我又开始从头学习flutter了:
浏览dart.dev/
浏览book.flutterchina.club/本想看下视频实战的,后面发现效率太低(有点啰嗦),放弃了。最终还是决定通过阅读flutter项目源码学习,事实上还是这种效率最高。
刚好公司有新app开发,这次决定用flutter开发了,边开发边学习,既完成了工作又完成了学习(ps:现在公司ios和前端也在学了😂)。
用完flutter的感受是,一旦接受这种嵌套布局后,发现布局也没那么难,hot reload牛皮,async真好用,dart语言真方便,嗯,香啊。
下面就此次app开发记录相关要点(菜鸟阶段,欢迎指正)
第三方库
dio: 网络
sqflite: 数据库
pull_to_refresh: 下拉刷新,上拉加载
json_serializable: json序列化,自动生成model工厂方法
shared_preferences: 本地存储
fluttertoast: 吐司消息
图片资源
为适配各个分辨率的图片资源,通常需要1,2,3倍的图。在flutter项目根目录下创建assets/images目录,在pubspec.yaml文件中加入图片配置
flutter:
# ...
assets:
- assets/images/
然后通过sketch切出1/2/3倍图片,这里可通过编辑预设,在词首加入2.0x/和3.0x/,这样导出的格式便符合flutter图片资源所需了。
这里再建一个image_helper.dart的工具类,用于产生Image
class ImageHelper {
主界面Tab导航
在app主界面,tab底部导航是最常用的。通常基于Scaffold的bottomNavigationBar配和PageView使用。
通过PageController控制PageView界面切换,同时使用BottomNavigationBar的currentIndex控制tab选中状态。为了能使监听返回键,使用WillPopScope实现点两次返回键退出app。
List pages =
网络层封装
网络框架使用的是dio,不管是哪种平台,网络请求最终要转成实体model用于ui展示。这里先将dio做一个封装,便于使用。
https://github.com/flutterchina/dio
通用拦截器
网络请求中通常需要添加自定义拦截器来预处理网络请求,往往需要将登录信息(如user_id等)放在公共参数中,例如;
import
Dio封装
然后使用dio封装get和post请求,预处理响应response的code。假设我们的响应格式是这样的:
{
code:0,
msg:"获取数据成功",
result:[] //或者{}
}
import
map转model
使用dio可以将最终的请求响应response转成Map对象,我们还需要将map转成相应的model。假如我们有一个获取文章列表的接口响应如下:
{
code:0,
msg:"获取数据成功",
result:[
{
article_id:1,
article_title:"标题",
article_link:"https://xxx.xxx"
}
]
}
就需要一个Article的model。由于Flutter下是禁用反射( https://flutter.dev/docs/development/data-and-backend/json#is-there-a-gsonjacksonmoshi-equivalent-in-flutter )的,我们只能手动初始化每个成员变量。不过我们可以通过json_serializable( https://pub.dev/packages/json_serializable )将手动初始化的工作交给它。首先在pubspec.yaml引入它:
dependencies:
我们创建一个article.dart的model类:
import
注意这里引用到了一个article.g.dart没有产生的文件,我们通过pub run build_runner build命令就会生成这个文件
// GENERATED CODE - DO NOT MODIFY BY HAND
然后在article.dart里添加工厂方法
class Article{
具体请求封装
创建好model类后,就可以建一个具体的api请求类ApiRepository,通过async库,可以将网络请求最终封装成一个Future对象,实际调用时,我们可以将异步回调形式的请求转成同步的形式,这有点和kotlin的协程类似:
import
实际调用
封装好网络请求后,就可以在具体的组件中使用了。假设有一个_ArticlePageState:
import
数据库
数据库操作通过sqflite,简单封装处理事例了文章Article的插入操作。
https://pub.flutter-io.cn/packages/sqflite
import
Android层兼容通信处理
为了兼容底层,需要通过MethodChannel进行Flutter和Native(Android/iOS)通信
flutter调用Android层方法
这里举例flutter端打开系统相册意图,并取得最终的相册路径回调给flutter端。我们在Android中的MainActivity中onCreate方法处理通信逻辑
"event")
因为是通过result.success将结果回调给Flutter端,所以封装了打开相册的工具类。
object PictureUtil {
然后在PictureFragment中加入callback,并且处理onActivityResult逻辑
class PictureFragment : Fragment() {
这里FileUtil.getFilePathByUri是通过data获取相册路径逻辑就不贴代码了,网上很多可以搜索一下。然后在flutter端使用
void _openPicture()
Android端调用Flutter代码
将刚刚MainActivity中的eventChannel声明成类变量,就可以在其他地方使用它了。比如推送通知,如果需要调用Flutter端的埋点接口方法。
class MainActivity : FlutterActivity() {
在Firebase消息通知中调用Flutter方法
class FirebaseMsgService : FirebaseMessagingService() {
然后在Flutter层我们添加回调
class
源码参考:
https://github.com/iamyours/Wandroid/tree/flutter
●编号655,输入编号直达本文
●输入m获取到文章目录
推荐↓↓↓Java编程
更多推荐《25个技术类公众微信》
涵盖:程序人生、算法与数据结构、黑客技术与网络安全、大数据技术、前端开发、Java、Python、Web开发、安卓开发、iOS开发、C/C++、.NET、Linux、数据库、运维等。