flutter学习笔记

flutter与RN的异同

  • 均实现了跨平台
  • 都支持热重载,开发调试非常方便
  • RN基于React,使用js开发,受众较广,flutter则是使用Dart,受众小,对于Java开发人员来说非常友好
  • 通俗来讲,RN的UI框架是将JS转化为原生控件,所以流畅度会比webview要高,而flutter则是从更底层进行控件的绘制,直接废弃了原生UI控件,性能要比RN更高!可以将flutter的应用理解成一个跨平台的游戏引擎写的游戏APP。
  • RN发展较早,比flutter稳定,flutter的第三方库还很少

flutter界面控件

在flutter中,所有控件都是widget,页面(可以理解成Android的activity,iOS的controller)和应用程序自身都是一个widget。

flutter中存在两种widget,StatelessWidget用于定义无状态控件,适用于显示静态文字、图片等,这种控件在编译运行后无法更新内容;StatefulWidget用于定义有状态控件,后期可以通过调用setState方法来刷新内容,用途更广,更灵活。

flutter自带了Material Design的整套UI设计控件,可构建非常完整MD风格的APP,也拥有用于当前iOS设计语言的美丽和高保真widget。

详细widget控件目录可浏览flutter中文官网

flutter构建页面

在flutter中页面自身也是widget,以下示例中的MaterialApp控件提供了MD风格的整套UI模板,另外也有针对iOS风格的CupertinoApp

import 'package:flutter/material.dart'; 
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // 这个widget是这个应用的根部widget
  @override
  Widget build(BuildContext context) { 
    return MyHomePage();
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);
  // 这是应用的主页widget,同时它是一个有状态的widget,意味着它可以动态刷新内容
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() { 
      //当你调用setState方法时,会通知framework触发build方法,刷新UI界面
      _counter++; 
    });
  }

  @override
  Widget build(BuildContext context) {
    //当你条用setState方法,build方法就会被触发,刷新UI
    return  MaterialApp(
    //设置路由
     routes: < String, WidgetBuilder > {

      '/a':(_) => PageA(),
      '/b':(_) => PageB()},
      title: 'Flutter Demo',
      home: Scaffold(
        backgroundColor: Colors.white70,
        appBar: AppBar(
          title: Text('hello flutter'),
        ),
        body: Center( 
          child: Text('hello flutter onclick-count = $_counter'),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: _incrementCounter,
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

Screenshot_1550475894.png

值得注意的是MyApp自身是StatelessWidget,是无状态的widget,但由于它内部存在StatefulWidget,所以它是可以通过StatefulWidget来更改UI

flutter触摸事件

flutter中,除了RaisedButton、FlatButton、IconButton等一系列按钮控件外,其余widget是不具备onPressed属性的,但是flutter提供了一个更加强大的手势监听widget:GestureDetector,支持单机、双击、长按等常见触摸事件,当你某个widget需要某些触摸事件时,可在GestureDetector嵌套该widget。

GestureDetector(
            //双击
            onDoubleTap: (){

            },
            //长按
            onLongPress: (){

            },
            //单击
            onTap: (){

              _incrementCounter();
            },
            child: Text('hello flutter onclick-count = $_counter'),
          ), 

flutter页面跳转

路由分为静态路由和动态路由

静态路由

有两种注册方式
1.修改主方法,用MaterialApp或其他WidgetsApp来包裹MyApp,设置路由

void main() => runApp(MaterialApp(home: MyApp(),
  routes: < String, WidgetBuilder > {

      '/a':(_) => PageA(),//页面A
      '/b':(_) => PageB()//页面B 
  },
)); 

2.直接在MyApp的类中设置属性,请参考flutter构建页面这一章节

然后通过

//切换到B页面
 Navigator.pushNamed(context, '/b');

动态路由

动态路由则不需要事先注册,灵活度更高,使用方式更多,方便传值以及设置转场动画

Navigator.push(context, PageRouteBuilder(pageBuilder: (BuildContext context, Animation < double > animation,
              Animation < double > secondaryAnimation) {
              //下一个页面
              return Center(
                child: GestureDetector(
                  onTap: () {
                    //返回上一个页面
                    Navigator.pop(context);
                  },
                  child: Text('haha'),
                ),
              );
            //构建转场动画
            }, transitionsBuilder: (BuildContext context,
              Animation < double > animation,
              Animation < double > secondaryAnimation,
              Widget child) {
                //自定义转场动画
              return new SlideTransition(
                position: new Tween < Offset > (
                  begin: const Offset(3.0, 0.0),
                    end: const Offset(0.0, 0.0),
                ).animate(animation),
                child: child,
              ).build(context);
            }));

如果你想使用系统默认的动画,推荐直接使用MaterialPageRoute

Navigator.push(context,MaterialPageRoute(builder: (context){
              //下一个页面
              return Center(
                child: GestureDetector(

                  onTap: () {
                    //返回上一页
                    Navigator.pop(context);
                    //返回上一页,并且返回一个200的值,可以是其他值,用于回调场景
                    //Navigator.pop(context,200);

                  },
                  child: Text('haha'),
                ),
              );
              //用于接收下一个页面返回的值
            })).then((data){


              print(data);
            });

建议通过自定义StatefulWidget来构建下一个可刷新的页面,更便于传值

Navigator.push(context,MaterialPageRoute(builder: (context){
              //Page为StatefulWidget参数即可达到传值的效果
              return Page(id:'1023');
            }));

flutter与原生交互

Android

首先,在flutter中声名如下方法

 Future<Null> _tryConnectAndroid() async {
      
          try { 
              //注册方法频道
              MethodChannel platform = MethodChannel('samples.test/test');
              //第一个参数 tryToast为Java/oc中的方法名(后面会讲),第二个参数数组为传参数组
              String result= await platform.invokeMethod('tryToast',[{'msg':"flutter connect android"}]);}
              //result 为回调的结果
              on PlatformException catch (e){ 
                  
              }
 
    }

然后在flutter项目的Android目录找到MainActivity

public class MainActivity extends FlutterActivity {
  //需要与flutter的MethodChannel名称对应
  static String CHANNEL="samples.test/test";
  private int count = 0;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GeneratedPluginRegistrant.registerWith(this);
     //注册方法
    new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
      new MethodCallHandler() {
          @Override
          public void onMethodCall(MethodCall call, Result result) {
              //找到对应的方法名
              if (call.method.equals("tryToast")) {
                  //传递过来的参数列表
                  ArrayList arguments = (ArrayList)call.arguments;
                  String msg =((Map<String,String>)arguments.get(0)).get("msg");
                  //回调结果
                  result.success("hello flutter");
                // start();
                Toast.makeText(MainActivity.this,msg,Toast.LENGTH_LONG).show();

              }

          }
      });
  }


  
}

iOS

iOS的请参考此链接

flutter打包apk与ipa

apk打包

apk打包相对简单,和以往的Android打包一样,在gradle文件里配置好签名信息等,运行一下指令即可

flutter build apk

IPA的请参考此链接

总结

学习flutter两三个星期,一开始被它多重嵌套的UI写法吓到了,后来习惯下来还是比较得心应手的,虽然写UI的时候不能像Android写xml一样能够即使预览,但是得益于热重载的功能,实际上你一边写UI一边在模拟器和手机上预览UI也是完全没有问题的。flutter提供了大量的UI控件,方便开发者灵活使用,像上文所说,flutter是直接抛弃了原生控件,通过图像引擎利用Android/iOS的画布将UI绘制出来,性能当然要比RN通过JavaScript转换成原生UI控件要高,通过Android手机查看基于flutter缩写APP的UI层级时,会发现APP的UI只有一个层级,它是一个整体的View,不像以往Android需要进一步优化布局层级。

flutter的定义是极速构建漂亮的原生应用,是一套移动UI框架,flutter只是能够帮助开发者更有效率地构建UI,如果APP的业务需要调用大量的手机系统特性时,开发者仍需要转移到原生开发中,所以开发者能够同时掌握Android、iOS开发就最好不过了。

更多关于flutter的文档可查阅此链接

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容