Flutter

[TOC]

0x00 Flutter

flutter是google開發(fā)的移動(dòng)端UI框架除师,支持android和ios宾濒。該框架使用dart語(yǔ)言進(jìn)行開發(fā)厘唾,在skia的基礎(chǔ)上開發(fā)了一套公共組件達(dá)到android與ios共用代碼的目的瀑踢。

1. Flutter系統(tǒng)架構(gòu)

flutter_arch.png

2. Platform Channels

flutter使用methodChannel/flutterMethodChannel來訪問系統(tǒng)原生api悯辙。


platform_channels.png

0x01 使用Flutter開發(fā)應(yīng)用程序

1. 下載配置Flutter SDK

  • 由于眾所周知的原因,我們首先需要進(jìn)行如下配置货裹,讓flutter通過國(guó)內(nèi)鏡像下載sdk等依賴嗤形。
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
  • 安裝sdk
$ git clone -b beta https://github.com/flutter/flutter.git
$ export PATH=`pwd`/flutter/bin:$PATH
  • 使用flutter doctor檢測(cè)本機(jī)環(huán)境,然后根據(jù)提示安裝依賴軟件弧圆。
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[?] Flutter (Channel beta, v0.1.5, on Mac OS X 10.11.6 15G19009, locale zh-Hans)
[?] Android toolchain - develop for Android devices (Android SDK 27.0.3)
[!] iOS toolchain - develop for iOS devices (Xcode 7.2.1)
    ? Flutter requires a minimum Xcode version of 9.0.0.
      Download the latest version or update via the Mac App Store.
    ? ios-deploy not installed. To install:
        brew install ios-deploy
    ? CocoaPods not installed.
        CocoaPods is used to retrieve the iOS platform side's plugin code that responds to your plugin usage on the Dart side.
        Without resolving iOS dependencies with CocoaPods, plugins will not work on iOS.
        For more info, see https://flutter.io/platform-plugins
      To install:
        brew install cocoapods
        pod setup
[?] Android Studio (version 3.0)
[?] Android Studio (version 2.3)
[!] IntelliJ IDEA Community Edition (version 2017.2.6)
    ? Flutter plugin not installed; this adds Flutter specific functionality.
[!] VS Code (version 1.21.0)
[!] Connected devices
    ! No devices available

! Doctor found issues in 4 categories.

2. 使用Android Studio開發(fā)Demo

1. 創(chuàng)建應(yīng)用

create_flutter_app_1.png
create_flutter_app_2.png
create_flutter_app_3.png
create_flutter_app_4.png

2. 項(xiàng)目結(jié)構(gòu)

使用android studio創(chuàng)建出來的項(xiàng)目目錄結(jié)構(gòu)大致如下:

  • ios目錄包含了ios的全部代碼可以直接使用xcode(需要9.0+版本)進(jìn)行開發(fā)赋兵。
  • android目錄包含了android的全部代碼,直接使用android studio開發(fā)即可搔预。
  • lib目錄中包含了兩端通用的dart代碼霹期,在打包生成應(yīng)用時(shí),全部的dart代碼會(huì)被編譯為本地代碼(如在android端拯田,會(huì)被直接編譯為so文件)历造。
app_struct.png

3. 調(diào)試與運(yùn)行

  • 選擇android/ios設(shè)備,然后點(diǎn)擊運(yùn)行按鈕就可以將應(yīng)用運(yùn)行到android/ios設(shè)備上船庇。


    app_select_device_and_run.png
  • 點(diǎn)擊調(diào)試安妮運(yùn)行app吭产,就可以調(diào)試dart代碼,調(diào)試界面與java完全一樣鸭轮。


    app_debug.png

4. 熱加載

flutter中熱加載的概念和android開發(fā)中的Instant run類似垮刹,同樣也是點(diǎn)擊??按鈕啟用熱加載功能。但是其擁有以下優(yōu)點(diǎn):

  1. 點(diǎn)擊保存按鈕或者保存快捷鍵张弛,也會(huì)觸發(fā)熱加載功能(??按鈕功能相同)荒典。
  2. 熱加載會(huì)保留先前的狀態(tài)酪劫。
  3. 快!快寺董!快覆糟! 代碼增量編譯在秒級(jí)別,單行代碼改變反應(yīng)到應(yīng)用程序UI改變耗時(shí)約1.5秒左右遮咖。

所以大家就可以像寫web頁(yè)面一樣滩字,可以邊寫->邊保存->邊查看效果,開發(fā)效率大大加快有沒有御吞,再也不用等等等有沒有麦箍。。陶珠。

熱加載前 代碼變動(dòng) 熱加載后
可以看到應(yīng)用程序的計(jì)數(shù)器的值是2.
app_hot_reload_before.png
修改字符顯示挟裂,添加“吼吼吼吼”到文本中,然后保存觸發(fā)熱加載揍诽。
app_hot_reload_with_state.png
可以看到文本字符發(fā)生改變诀蓉,但是計(jì)數(shù)器的值未發(fā)生變化,仍然是2.
app_hot_reload_after.png

5. 應(yīng)用程序結(jié)構(gòu)與兼容性

1. 應(yīng)用程序結(jié)構(gòu)

  • Debug (slow mode模式)

首先我們打開項(xiàng)目根目錄中的build文件夾暑脆,該文件包含了編譯app的全部生成文件渠啤,其結(jié)構(gòu)與android應(yīng)用程序一致(注意:build目錄在android studio中不顯示,可以通過terminal打開或查看)添吗。

apk_location.png

接下來沥曹,我們可以通過android studio直接打開該apk,可以發(fā)現(xiàn)僅僅只有一個(gè)頁(yè)面的flutter應(yīng)用大小已經(jīng)達(dá)到了25MB左右碟联,分析其結(jié)構(gòu)(見下圖)妓美,其包含了全部abi類型的so文件,導(dǎo)致apk整體比較大玄帕,排除掉x86部脚、x86_64平臺(tái)的so文件之后想邦,apk整體大小約11MB左右裤纹。

apk_struct_with_dart-1.png

  • Release模式

使用release模式時(shí),apk大小約8.1MB丧没,大小比較正常鹰椒。

apk_struct_mode_release.png

2. 應(yīng)用程序兼容性

  • andorid最低支持到 api 16;
  • ios最低支持到ios 8.0;

3. 開發(fā)Toast模塊

這里我們直接使用android studio進(jìn)行開發(fā),如果大家需要直接使用flutter進(jìn)行創(chuàng)建的話呕童,可以直接參考platform-channels進(jìn)行開發(fā)漆际。

1. 使用dart編寫公共的toast模塊

import 'package:flutter/services.dart';

// 下劃線開頭的變量只在當(dāng)前package中可見。
const _toast = const MethodChannel('com.coofee.flutterdemoapp/sdk/toast');

const int _LENGTH_SHORT = 0;

const int _LENGTH_LONG = 1;

void show(String text, int duration) async {
  try {
    await _toast.invokeMethod("show", {'text': text, 'duration': duration});
  } on Exception catch (e) {
    print(e);
  } on Error catch (e) {
    print(e);
  }
}

void showShort(String text) {
  show(text, _LENGTH_SHORT);
}

void showLong(String text) {
  show(text, _LENGTH_LONG);
}

2. 編寫android端的代碼并注冊(cè)

package com.coofee.flutterdemoapp;

import android.os.Bundle;
import android.widget.Toast;

import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        GeneratedPluginRegistrant.registerWith(this);

        new MethodChannel(getFlutterView(), "com.coofee.flutterdemoapp/sdk/toast")
                .setMethodCallHandler(new MethodChannel.MethodCallHandler() {
                    @Override
                    public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
                        if ("show".equals(methodCall.method)) {
                            String text = methodCall.argument("text");
                            int duration = methodCall.argument("duration");
                            Toast.makeText(MainActivity.this, text, duration).show();
                        }
                    }
                });
    }
}

3. 編寫ios端代碼并注冊(cè)

ios端的代碼與android端類似夺饲,但是需要使用FlutterMethodChannel進(jìn)行處理奸汇,其他操作與android端一致施符,打開AppDelegate.m文件,添加如下代碼:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];

  FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;

  FlutterMethodChannel* toastChannel = [FlutterMethodChannel
                                            methodChannelWithName:@"com.coofee.flutterdemoapp/sdk/toast"
                                            binaryMessenger:controller];

  [toastChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
      if ([@"show" isEqualToString:call.method]) {
          // 展示toast;
          NSLog(@"顯示toast....")
      }
  }];

  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

4. 在flutter中調(diào)用toast模塊

import 'sdk/toast.dart';

void _incrementCounter() {
  showShort('你點(diǎn)擊了$_counter次');

  setState(() {
    // This call to setState tells the Flutter framework that something has
    // changed in this State, which causes it to rerun the build method below
    // so that the display can reflect the updated values. If we changed
    // _counter without calling setState(), then the build method would not be
    // called again, and so nothing would appear to happen.
    _counter++;
  });
}

5. 效果

toast_show.png

0x02 使用Dart 2

1. 升級(jí)flutter sdk

使用dart 2時(shí)擂找,必須保證戳吝,F(xiàn)lutter SDK版本必須大于等于以下版本:

  • Beta channel: build 0.1.4 from 2018-02-19, or later
  • Dev channel: build from 2018-02-22, or later
  • Master channel: build from 2018-02-20, or later

在Terminal中執(zhí)行flutter --version命令,查看flutter的版本:

→ flutter --version
Flutter 0.1.5 ? channel beta ? https://github.com/flutter/flutter.git
Framework ? revision 3ea4d06340 (3 weeks ago) ? 2018-02-22 11:12:39 -0800
Engine ? revision ead227f118
Tools ? Dart 2.0.0-dev.28.0.flutter-0b4f01f759

在Terminal中執(zhí)行flutter upgrade可以升級(jí)flutter贯涎。

2. 在android studio中啟用dart 2

在android studio中啟用dart2后,需要重啟android studio使其生效塘雳。

dart-2.png

3. dart 1 vs dart 2

從下圖可以看出dart2相對(duì)于dart1來說陆盘,省略了關(guān)鍵字new,使得聲明式布局的可讀性更進(jìn)一步败明。

dart1_vs_dart2.png

4. dart2對(duì)apk大小的影響

從下圖可以看出來隘马,使用dart2時(shí)生成的apk比dart1打5MB左右(slow mode模式)。

apk_dart1_vs_dart2.png

0x03 Flutter's modes

從下圖我們可以看到肩刃,flutter mode顯示在在app的右上角祟霍。

mode_slow.png

flutter的應(yīng)用程序有以下4中模式,分別使用不同的命令生成盈包,且不同模式下生成的應(yīng)用大小不一(如:release模式會(huì)去掉x86相關(guān)的so文件)

mode 命令
debug flutter run debug模式下的產(chǎn)物沸呐,且應(yīng)用的右上角會(huì)顯示slow mode字樣,支持debug呢燥。
release flutter run --release UI上面不顯示模式崭添;禁止debug,且刪除了debug相關(guān)的信息叛氨;關(guān)閉全部的斷言檢測(cè)呼渣,減小包大小,使其達(dá)到最佳性能寞埠。
profile flutter run --profile 調(diào)試性能屁置,不支持模擬器。
test flutter test 和debug模式類似仁连,不支持headless和桌面平臺(tái)蓝角。

0x04 參考引用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市饭冬,隨后出現(xiàn)的幾起案子使鹅,更是在濱河造成了極大的恐慌,老刑警劉巖昌抠,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件患朱,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡炊苫,警方通過查閱死者的電腦和手機(jī)裁厅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門冰沙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人执虹,你說我怎么就攤上這事倦淀。” “怎么了声畏?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵撞叽,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我插龄,道長(zhǎng)愿棋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任均牢,我火速辦了婚禮糠雨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘徘跪。我一直安慰自己甘邀,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布垮庐。 她就那樣靜靜地躺著松邪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪哨查。 梳的紋絲不亂的頭發(fā)上逗抑,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音寒亥,去河邊找鬼邮府。 笑死,一個(gè)胖子當(dāng)著我的面吹牛溉奕,可吹牛的內(nèi)容都是我干的褂傀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼加勤,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼仙辟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起胸竞,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤欺嗤,失蹤者是張志新(化名)和其女友劉穎参萄,沒想到半個(gè)月后卫枝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡讹挎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年校赤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吆玖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡马篮,死狀恐怖沾乘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情浑测,我是刑警寧澤翅阵,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站迁央,受9級(jí)特大地震影響掷匠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜岖圈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一讹语、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蜂科,春花似錦顽决、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至贡定,卻和暖如春鸠儿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背厕氨。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工进每, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人命斧。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓田晚,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親国葬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贤徒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容