第六节:主要讲布局模式
第七节:项目搭建,以及安卓的图标配置
安卓图标名不可驼峰,图标只需要关注xpdpi就是ios的2X,xx就是3X,闪屏图放到m-hdpi,然后在main文件下的lanuch- xml文件里修改名字即可。
如何导入全部图片?复制本地图片,到项目中粘贴,然后再pubspec.yaml文件中解开注释 assets: 注意这边要删掉前面的空格,包括下面images前面的空格,路径选择到/images根目录下即可。
第八节:项目布局,push 界面调整
第九节 第十节 通讯录的索引条&聊天准备
这里介绍了回调的使用
简单的系统弹框
制作网络假数据
网络请求方式
第十一节 聊天界面数据处理
网络请求以后json数据转model数据
本地数据保留防止被销毁
异步简单介绍:
flutter属于单线程,但是可以开启异步防止UI堵塞,具体是把任务丢给Future处理,把结果返回给Future,通过then去处理返回的value。
如果是需要在当前方法获取的数据以后返回数据,这个数据的获取需要等待,那可以参考一下。需要注意的是一定要配合async和await一起,否则无法生效。
void getData() async{
print("开始任务");
await Future((){
for (int i = 0 ; i < 1000000000; i++){
data = "222";
}
});
print("任务结束:${data}");
}
第十二节 单线程队列处理 & 多线程
在做异常处理的时候,要把catcherror放到最后,防止报错,因为catcherror返回的对象跟其他链式调用的对象不是同一个类型。
在flutter中,对于future包装的任务,是放到串行队列中,多个任务可以用wait包装,执行顺序不会变。
在dart中使用多线程处理数据,关键字Isolate,数据独立,不存在资源强夺。
第十三节 dio展示案例
多线程和队列混合案例
简单的网络封装
第十四节 searchBar
回调方法 ~ 35
第十五节 生命周期和渲染
生命周期就是一些方法的回调,
数据共享的实现方式:通过在父节点构造一个便捷方法,把需要监听的数据和对应的子组件传进去,在发生改变的时候updateShouldNotify这个方法中返回true,那么在接收改变的地方MyData.of(context)!.data,就可以拿到更新以后的数据,这里的MyData就是你新创建的数据类,data就是监听的数据。
widget树,renderobjc树,element树,任何widget树进来都会创建element树,两者是一一对应的关系,在调用完了element树的mount方法,会判断是否是renderobjectElement对象,如果是会创建renderobjc树。
第十六节 key的原理和混合开发(上)
总体来说有两种key,GloableKey和LocalKey,前者可以通过给stateful绑定这个key,在任何其他的组件中访问这个key绑定的的widget、context、state,state类中的数据也完全可以访问。 后者主要是标识区别增删的数据,localkey有三个子类,valueKey(任意类型作为值),objectKey(任意对象类型)和uniqueKey(唯一标识)。
混合开发 ~ 29
ImagePicker 官网的使用以及异常处理。
之后的工作,混合开发,热重载原理,插件、包,混合工程自动化,本地存储缓存。
第十七节 混合开发 & flutter引擎
如果希望在原生嵌入Flutter界面,创建Module项目,必须是纯flutter工程,不能含有原生的代码引用。通过cocopods关联,如果有路径问题,详情参阅这位朋友的解决方法:www.jianshu.com/p/c36b1873a…
原生和flutter之间的点击回调事件响应。
跳转到flutter界面,会加载整个flutter引擎,内存很大,大概是90MB左右。
解决:通过引擎构造控制器,并且在viewdidiload的时候就初始化创建
self.flutterVC = [[FlutterViewController alloc]initWithEngine:self.flutterEngine nibName:nil bundle:nil];
引擎的构造方法
**if** (_flutterEngine == **nil**){
FlutterEngine *engine = [[FlutterEngine alloc]init];
**if** (engine.run) {
_flutterEngine = engine;
}
}
**return** _flutterEngine;
}
在flutter中创建channel直接通过构造方法,而在oc中需要通过调用methodChannelWithName创建,发送消息用invoke,接受用setcallHandle。两边channel之间通过name联通,name就是所属的界面,handle里拦截可以通过方法method去取,同时通过argm去获取参数,当然,invoke会自带这俩参数。
在做的时候可能会碰到flutter Command PhaseScriptExecution failed with a nonzero exit code这种问题,搜了一下,有很多原因会导致这个错误,不要盲目改,新的测试项目是不可能有那些乱七八糟的问题的,找到打印的error信息,根据error去解决,我这里是导入了没必要的dart.html去掉就可以了,警告不用管,警告不会导致编译错误。
第十八节 引擎的关联和底层channel
下载需要梯子,中途可能多次中断,大小15G,编译完26G。
引擎的版本号必须与你本地的channel的版本号一致
每次修改引擎源码都要重新编译才能生效。
每一种channel都有自己的编解码器,但是底层实现都是通过FlutterStandardReadWriter类实现。在调用写入(invoke)的时候,会分别判断各个值的类型,带上标志位字节一起写入进去(为了保证三个端数据能够统一用了标志位)。
第十九节 插件开发、热重载原理
package 和 插件区别在于,前者只有dart代码,后者有原生部分。
发布:1.需要梯子,终端也需要翻2.需要谷歌账号授权,3.需要证书,可以通过github创建BSD3获取复制放到工程中的文件中。4.如果官方发布卡住可以指定镜像。注意,包的资源文件需要放到lib文件下,打包只会打包lib文件夹。资源要指定包下面的资源防止资源冲突,比如image下通过AssertImage package.
开发插件:一般是需要跟原生有交互通讯才会用到,插件自带example,
第二十节 热重载原理 & 混合工程自动化
热重载:苹果上架是不支持热重载更新的,但是如果要做也不是不行,就是要把server端本地开发,搭建自己的服务端,flutter检测到代码改变以后,让服务端去处理然后给flutter的渲染引擎去刷新。
混合工程自动化:在没有搭建flutter环境时,如何让原生能够顺利引入flutter的工程保证混合开发,而不需要他去配置flutter环境,这就是混合工程自动化要做的事情。
1.通过framework构建:在flutter工程目录下构建,命令flutter build ios-framework --output=../flutter_app 成功以后会生成三个文件夹,对应ios原生的两种debug和release,flutter多出了一种profile介意两者之间,既有release的性能,又兼备debug的调试功能。每个版本里有两个framework,一个是app一个是flutter,前者是显示代码界面,后者是flutter的sdk,把任意一个版本文件下拷贝到原生工程的根目录中即可。最后在原生工程中导入这两个framework就可以。
2.通过cocopods构建:同样来到文件下命令:flutter build ios-framework --cocoapods --output=../Flutter_app 通过pod创建。
如何自动打包?
如果是多人开发,那不可能每次打包完了再发给对方让对方替换这样比较麻烦,这种情况可以借助git仓库管理,利用脚本去实现。
首先在创建完仓库并且上传完了本地文件以后,在git的action中添加对应的脚本信息,然后执行,等待执行结束,就会在本地仓库中看到编译好的三个文件已经在原生工程路径下了,如果是通过cocoapods创建,那么在本地再创建一个podfile文件去执行关联并且导入framework就可以了。
本地存储
1.轻量级数据用SharedPreferences,原理是引用了ios的Userdefault。
我这边跳出提醒说没有安装cocoapods,很明显这个错误很弱智,第一种方法是直接通过AS的命令行运行flutter run。但是这种方法太麻烦,第二种是退出AS和Xcode,重新打开AS项目,进入ios目录,执行podInstall,也是很弱智,之前没全部关闭之前执行过了还是报错,必须关闭了在执行才行。
2.数据量较大,使用数据库。sqflite
sqflite: ^2.2.5
path方便拼接。
path: ^1.8.3
provide 用法
provide 用于快速通知监听改变的数据,相对于数据共享来说,更加简单方便使用。而数据共享只能是单向的,两者的共同点是必须建立在要传递类的根节点。provide监听到数据的改变会通知对应共享的数据所在的组件重新刷新build。
问题:由于provide监听渲染是重新刷新build,有一些不需要更新的组件也会刷新,所以需要优化,provide提供了Consumer组件,在内部传入三个参数,第一个就是当前的context,第二个是监听改变的数据,第三个就是不需要改变的组件child。
需要注意的是,如果添加的根节点,在最顶层,那么添加在Material的home是无效的会报错,必须把整个Material放进去。