写点什么

一位 Android 程序员入坑 Flutter 后整理出一份超详细的学习笔记

用户头像
Android架构
关注
发布于: 刚刚
  • Row对应的就是 LinearLayout + Horizontal,Column对应的就是 LinearLayout + Vertical,他们都具备一个属性叫做crossAxisAlignment,有点类似gravity,来控制子 View 相对于父 View 的位置。

  • Expanded支持一个类似 weight 的属性,叫flex

  • Container是一个具有decoration属性的容器,可以用来控制背景色,border, margin 等等。

  • Stack有点像是一个特殊的 RelatetiveLayout 或者 ConstraintLayout,children属性指定了它的子 View,第一个是 Base View,alignment属性指定了后面的子 View 相对于 BaseView 的位置,如alignment: const Alignment(0.6, 0.6)指定了位于 BaseView 右下角的位置。

  • ListTile是一个特殊的 ListItem,有三个属性,分别是左边的 Icon (leading),文字 (title),以及右边的 Icon (trailing)。

  • 还有诸如ListViewGridViewCard等等比较熟悉的 Widgets。


另外有一个类似于我们 Activity 的 Widgets:


  • 叫做MaterialApp, 可以指定theme,?title, 以及子 View?home, 还有更重要的页面跳转routes.


MaterialApp(


title: 'Welcome to Flutter',


home: ...,


routes: <String, WidgetBuilder> ...,


theme: ThemeData(


primaryColor: Colors.white


),


)


还有一个类似于 Fragment 的:


  • 叫做Scaffold,中文意思是脚手架,它包含一个 appBar (ActionBar)与一个 body,appBar 可以指定 title 与 actions (类似于 action button 的点击事件)。


Scaffold(


appBar: AppBar(


title: Text(widget.title),


actions: <Widget>[...],


),


body: ...,


)

如何从父 View 中 Remove 一个元素

答案是没有... 因为在 Flutter 看来吗,Widgets 的树结构是不可以被更改的,但是如果想更改,则是通过 StatefulWidgets 的方法,通过 setState 来更改 Data,触发 Widgets 重绘,从而替换掉之前的 Widgets。


喜欢画 Canvas 的同学怎么办?


Flutter 同样支持,CustomPaint作为一个 Widgets 就支持传入一个实现CustomPainter抽象类的参数,而CustomPainter的抽象方法也类似于 Android View 的onDraw


void paint(Canvas canvas, Size size)


bool shouldRepaint(CustomPainter oldDelegate)

如何自定义 View

不用继承,而使用类似 Android ViewGroup 的办法,通过组合(composing)与封装的方法来实现,通过小 Widgets 组合成需要的新 Widgets。

页面跳转怎么办,四大组件之一的 Intent 跑哪里去了

貌似在讲类似于 Activity 的MaterialApp的时候剧透了...


就是使用NavigatorRoutes来实现界面跳转,实际上是整个 Widgets 的替换。


routes: <String, WidgetBuilder> {


'/a': (BuildContext context) => MyPage(title: 'page A'),


'/b': (BuildContext context) => MyPage(title: 'page B'),


'/c': (BuildContext context) => MyPage(title: 'page C'),


}


Navigator.of(context).pushNamed('/b');

如何处理外部的 Intent

实际上还是需要在 Flutter App 的 Android 壳子中注册这个 filter,然后在 FlutterActivity 中拿到存下来。


FlutterView 初始化后再通过 Bridge,官方叫MethodChannel从 Java 里获取,进行下一步逻辑。


可以看个简单的例子:


new MethodChannel(getFlutterView(), "app.channel.shared.data").setMethodCallHandler(


new MethodCallHandler() {


@Override


public void onMethodCall(MethodCall call, MethodChannel.Result result) {


if (call.method.contentEquals("getSharedText")) {


result.success(sharedText);


sharedText = null;


}


}


});


getSharedText() async {


var sharedData = await platform.invokeMethod("getSharedText");


if (sharedData != null) {


setState(() {


dataShared = sharedData;


});


}


}

常用的 startActivityForResult 怎么办.

这个 Flutter 有完全对应的办法,而且用起来很方便,结合之前说的页面跳转。


Map xxx = await Navigator.of(context).pushNamed('/xxx');


Navigator.of(context).pop({xxx});

异步怎么办, runOnUiThread()哪里去了

Flutter 有点像 JS,是一个单线程模式,所以只是通过模拟来构建简单的异步,关键字就是类似于 kotlin coroutines 一样,通过await+async来处理。


如:


loadData() async {


response = await http.get(xxx);


setState(() {xxx});


}


但是由于它的单线程,所以无法做很长的阻塞操作,像 http 请求的延迟正常情况可能都是毫秒级的,但是数据的处理等,可能就得秒级了。


这也是 RN 在线程方面的做 android 程序的一个痛点,Flutter 采用了比较容易想到的曲线救国的办法,提供了一个叫Isolate的对象,它实际是一个基于 socket 的数据通道,相当于把数据放在一个独立的


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


进程进行处理,然后再通过 socket 发送回程序进程,还记得进程间通信办法之一的管道吗...


具体 API 可以参考文档1...,2....

Flutter 替代 OkHttp 的网络库

自带了 http 库,直接http.get(url),在线程部分的代码实例里也有涉及。


通过类似 gradle 的文件pubspec.yaml引入。


dependencies:


...


http: ^0.12


^表示不升大版本,并取最新版本,比 gradle 的+要范围更小。

常见的 LCE(Loading Content Error)里面的 Loading 怎么 show

Flutter 有一个 widget 叫做ProgressIndicator,比如我们期望有一个转圈圈的 Loading 界面在数据加载出来之前。


我们就可以通过 StatefulWidgets,根据数据,或者 List Widgets 的个数 (如果是显示一个 List 的话)来判断是否显示 Loading,使用子类CircularProgressIndicator,来替换页面的 Widgets。


当然也是通过 setState(() {...})来触发界面刷新的,可以在 initState()内触发加载数据的异步操作。

不同分辨率的图片资源怎么放

这个有点像 iOS 了, 即有 1x,2x,3x:


images/my_icon.png // Base: 1.0x image


images/2.0x/my_icon.png // 2.0x image


images/3.0x/my_icon.png // 3.0x image


不一样的一点还需要添加到类似 gradle 的文件pubspec.yaml里。


assets:


  • images/my_icon.jpeg

字符串怎么存储

Flutter 没有像 Android 的string.xml的东西,目前来说最好的就就是存成静态字符串。


class Strings {


static String welcomeMessage = "Welcome To Flutter";


}


Text(Strings.welcomeMessage)

Gradle 变成什么了

前面说网络库,图片资源的时候提到过,提供了一个叫pubspec.yaml的文件,具体支持的规则可以查看这个文档

Fragment 与 Activity 呢?

之前做过类比,如MaterialApp有点类似于 Activity,而Scaffold都点类似 Fragment,实际上他们两个都是 Flutter 的 Widgets,也就是说其实只有 View 的概念了。

还有生命周期吗?

Flutter 有一个叫做WidgetsBinding的可以提供类似生命周期的回调。


四种状态inactive?(iOS 专用),paused(相当于 onPause,退后台),resumed(相当于 onPostResume,到前台),suspending(android 专用,相当于 onStop)。


一般在 StatefulWidgets 的 State 中注册与反注册。


@override


void initState() {


super.initState();


WidgetsBinding.instance.addObserver(this);


}


@override


void dispose() {


WidgetsBinding.instance.removeObserver(this);


super.dispose();


}

ScrollView vs ListView

Flutter 没有 ScrollView,合并到了 ListView,通过 ListView.builder 创建的 ListView 提供了 View 复用的逻辑。


ListView.builder(


itemCount: widgets.length,


itemBuilder: (BuildContext context, int position) {


return Text(xxx);


}))


其中 itemBuilder 有点像 Android ListView 的 getView,官方文档说它会自动回收 Element 给你,但是事实上每次你都需要根据 position 生成新的 Widgets,所以呢应该是 Flutter 在内部回收了之前的 Widgets 并在你重新创建的时候又用上了。


BTW,通过 ListView 构造来显示就不具备这种特性,所以大量数据需要用 Builder。

Flutter 横竖屏怎么玩

因为它实际上还是借助了 Android 程序的壳子,所以如果 AndroidManifect 定义了android:configChanges="orientation|screenSize",则 Flutter 会自己 hanlde。

怎么处理 Gesture

Flutter 提供了GestureDetector,它相当于一个 Container,将我们期望接收手势的 Widgets 放进去,再实现事件回调就行了。


GestureDetector(


child: FlutterLogo(


size: 200.0,


),

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
一位Android程序员入坑Flutter后整理出一份超详细的学习笔记