Flutter学习笔记

167 阅读8分钟

第六节:主要讲布局模式

第七节:项目搭建,以及安卓的图标配置

安卓图标名不可驼峰,图标只需要关注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放进去。