初識Flutter

Flutter是谷歌的移動UI框架,可以快速在iOS和Android上構建高質量的原生用戶界面。 Flutter可以與現有的代碼一起工作。在全世界,Flutter正在被越來越多的開發者和組織使用,并且Flutter是完全免費、開源的。

Flutter目標是使開發人員能夠交付在不同平臺上都感覺自然流暢的高性能應用程序。我們兼容滾動行為、排版、圖標等方面的差異。

Flutter組件采用現代響應式框架構建,這是從React中獲得的靈感,中心思想是用組件(widget)構建UI。 組件描述了在給定其當前配置和狀態時他們顯示的樣子。當組件狀態改變,組件會重構它的描述(description),Flutter會對比之前的描述, 以確定底層渲染樹從當前狀態轉換到下一個狀態所需要的最小更改。

它也是構建未來的Google Fuchsia應用的主要方式。

Dart語言:

Dart是谷歌開發的計算機編程語言,它被用于web、服務器、移動應用和物聯網等領域的開發。它是寬松開源許可證(修改的BSD證書)下的開源軟件。
Dart是面向對象的、類定義的、單繼承的語言。它的語法類似C語言,可以轉譯為JavaScript,支持接口(interfaces)、混入(mixins)、抽象類(abstract classes)、具體化泛型(reified generics)、可選類型(optional typing)和sound type system 。

快速開發

毫秒級的熱重載,修改后,您的應用界面會立即更新。
Flutter的熱重載可幫助您快速地進行測試、構建UI、添加功能并更快地修復錯誤。在iOS和Android模擬器或真機上可以在亞秒內重載,并且不會丟失狀態。

富有表現力和靈活的UI

Flutter內置美麗的Material Design和Cupertino(iOS風格)widget、豐富的motion API、平滑而自然的滑動效果和平臺感知,為用戶帶來全新體驗。





現代的,響應式框架

使用Flutter的現代、響應式框架,和一系列基礎widget,輕松構建您的用戶界面。使用功能強大且靈活的API(針對2D、動畫、手勢、效果等)解決艱難的UI挑戰。

class CounterState extends State<Counter> {
  int counter = 0;

  void increment() {
    // 告訴Flutter state已經改變, Flutter會調用build(),更新顯示
    setState(() {
      counter++;
    });
  }

  Widget build(BuildContext context) {
    // 當 setState 被調用時,這個方法都會重新執行.
    // Flutter 對此方法做了優化,使重新執行變的很快
    // 所以你可以重新構建任何需要更新的東西,而無需分別去修改各個widget
    return new Row(
      children: <Widget>[
        new RaisedButton(
          onPressed: increment,
          child: new Text('Increment'),
        ),
        new Text('Count: $counter'),
      ],
    );
  }
}

訪問本地功能和SDK

通過平臺相關的API、第三方SDK和原生代碼讓您的應用變得強大易用。 Flutter允許您復用現有的Java、Swift或ObjC代碼,訪問iOS和Android上的原生系統功能和系統SDK。

統一的應用開發體驗

Flutter擁有豐富的工具和庫,可以幫助您輕松地同時在iOS和Android系統中實現您的想法和創意。 如果您是一位iOS或Android開發人員,則可以使用Flutter作為視圖(View)層, 并可以使用已經用Java / Kotlin / ObjC / Swift完成的部分(Flutter支持混合開發)。

Flutter介紹視頻: https://youtu.be/fq4N0hgOWzU

Flutter框架概覽

Flutter包括一個現代的響應式框架、一個2D渲染引擎、現成的widget和開發工具。這些組件可以幫助您快速地設計、構建、測試和調試應用程序。

一切皆為widget

Flutter Widget框架概述

Widget是Flutter應用程序用戶界面的基本構建塊。每個Widget都是用戶界面一部分的不可變聲明。 與其他將視圖、控制器、布局和其他屬性分離的框架不同,Flutter具有一致的統一對象模型:widget。

Widget可以被定義為:

  • 一個結構元素(如按鈕或菜單)
  • 一個文本樣式元素(如字體或顏色方案)
  • 布局的一個方面(如填充)
  • 等等…

Widget根據布局形成一個層次結構。每個widget嵌入其中,并繼承其父項的屬性。沒有單獨的“應用程序”對象,相反,根widget扮演著這個角色。

您可以通過告訴框架使用另一個widget替換層次結構中的widget來響應事件,例如用戶交互,替換后框架會比較新的和舊的widget,并高效地更新用戶界面。

組合 > 集成

Widget本身通常由許多更小的、單一用途widget組成,這些widget結合起來產生強大的效果。例如,Container是一個常用的widget, 由多個widget組成,這些widget負責布局、繪制、定位和調整大小。 您可以用各種方式組合這些以及其他簡單的widget,而不是繼承容器。

類層次結構很淺且很寬,可以最大限度地增加可能的組合數量。


  • Stateless widgets 是不可變的, 這意味著它們的屬性不能改變 - 所有的值都是最終的.

  • Stateful widgets 持有的狀態可能在widget生命周期中發生變化. 實現一個 stateful widget 至少需要兩個類:

    1.一個 StatefulWidget類。
    2.一個 State類。 StatefulWidget類本身是不變的,但是 State類在widget生命周期中始終存在。

還可以通過與其他widget組合來控制widget的布局。例如,要將widget居中,可以將其封裝在Center widget中。有填充、對齊、行、列和網格的widget。 這些布局widget沒有自己的可視化表示。相反,他們唯一的目的是控制另一個widget布局的某些方面。要理解widget以某種方式呈現的原因,檢查相鄰widget通常很有幫助。

分層的框架

Flutter框架是一個分層的結構,每個層都建立在前一層之上。


這個設計的目標是幫助你用更少的代碼做更多的事情。例如,Material層是通過組合來自Widget層的基本Widget來構建的, 并且Widgets層本身是通過較低級對象渲染層構建的。

層為構建應用程序提供了許多選項。選擇一種自定義的方法來釋放框架的全部表現力,或者使用構件層中的構建塊,或混合搭配。 您可以實現Flutter提供的所有現成的widget,或者使用Flutter團隊用于構建框架的相同工具和技術創建您自己的定制widget。

構建widget

可以通過實現widget的build返回widget樹(或層次結構)來定義widget的獨特特征 。 這棵樹更具體地表示了用戶界面的widget層次。例如,工具欄widget的build函數可能返回一個包含一些文本和各種按鈕的水平布局。 然后,框架遞歸地構建widget,直到該所有widget構建完成,然后framework將他們一起添加到樹中。

widget的構建函數一般沒有副作用。每當它被要求構建時,widget應該返回一個新的widget樹,無論widget以前返回的是什么。 Framework會將之前的構建與當前構建進行比較并確定需要對用戶界面進行哪些修改。

這種自動比較非常有效,可以實現高性能的交互式應用程序。而構建函數的設計則著重于聲明widget是由什么構成的,而不是將用戶界面從一個狀態更新到另一個狀態的(這很復雜性),從而簡化了代碼。

處理用戶交互

如果widget需要根據用戶交互或其他因素進行更改,則該widget是有狀態的。例如,如果一個widget的計數器在用戶點擊一個按鈕時遞增,那么該計數器的值就是該widget的狀態。 當該值發生變化時,需要重新構建widget以更新UI。

這些widget將繼承StatefulWidget(而不是State)并將它們的可變狀態存儲在State的子類中。

每當你改變一個State對象時(例如增加計數器),你必須調用setState()來通知框架,框架會再次調用State的構建方法來更新用戶界面。

有了獨立的狀態和widget對象,其他widget可以以同樣的方式處理無狀態和有狀態的widget,而不必擔心丟失狀態。 父widget可以自由地創造子widget的新實例且不會失去子widget的狀態,而不是通過持有子widget來維持其狀態。 框架在適當的時候完成查找和重用現有狀態對象的所有工作。

Flutter Widget 索引

使用packages

Flutter支持使用由其他開發者貢獻給Flutter和Dart生態系統的共享軟件包。這使您可以快速構建應用程序,而無需從頭開始開發所有應用程序。

現有的軟件包支持許多使用場景,例如,網絡請求(http),自定義導航/路由處理(fluro), 集成設備API(如url_launcherbattery) 以及使用第三方平臺SDK(如 Firebase)。

搜索packages

Packages會被發布到了 Pub 包倉庫.

Flutter landing 頁面 顯示了與Flutter兼容的包。所有已發布的包都支持搜索。

將包依賴項添加到應用程序

要將包’css_colors’添加到應用中,請執行以下操作:

1.添加依賴

  • 打開 pubspec.yaml 文件,然后在dependencies下添加css_colors:

2.下載安裝

  • 在 terminal中: 運行 flutter packages get
    或者
  • 在 IntelliJ中: 點擊pubspec.yaml文件頂部的’Packages Get’

3.導入

  • 在您的Dart代碼中添加相應的import語句.

依賴未發布的packages

即使未在Pub上發布,軟件包也可以使用。對于不用于公開發布的專用插件,或者尚未準備好發布的軟件包,可以使用其他依賴項選項:

  • 路徑依賴: 一個Flutter應用可以依賴一個插件通過文件系統的path:依賴。路徑可以是相對的,也可以是絕對的。例如,要依賴位于應用相鄰目錄中的插件’plugin1’,使用以下語法
dependencies:
  plugin1:
    path: ../plugin1/
  • Git依賴: 你也可以依賴存儲在Git倉庫中的包。如果軟件包位于倉庫的根目錄中,請使用以下語法:
dependencies:
  plugin1:
    git:
      url: git://github.com/flutter/plugin1.git
  • Git 依賴于文件夾中的包: 默認情況下,Pub假定包位于Git存儲庫的根目錄中。如果不是這種情況,可以使用path參數指定位置,例如:
dependencies:
 package1:
   git:
     url: git://github.com/flutter/packages.git
     path: packages/package1  

使用平臺通道編寫平臺特定的代碼

Flutter使用了一個靈活的系統,允許您調用特定平臺的API,無論在Android上的Java或Kotlin代碼中,還是iOS上的ObjectiveC或Swift代碼中均可用。

Flutter平臺特定的API支持不依賴于代碼生成,而是依賴于靈活的消息傳遞的方式:

  • 應用的Flutter部分通過平臺通道(platform channel)將消息發送到其應用程序的所在的宿主(iOS或Android)。

  • 宿主監聽的平臺通道,并接收該消息。然后它會調用特定于該平臺的API(使用原生編程語言) - 并將響應發送回客戶端,即應用程序的Flutter部分。

消息和響應是異步傳遞的,以確保用戶界面保持響應。

示例:使用Java添加Android平臺特定的實現

1.添加平臺通道

在android -> java目錄中打開MainActivity.java.

接下來,在onCreate里創建MethodChannel并設置一個MethodCallHandler。確保使用與在Flutter客戶端使用的通道名稱相同。

import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;

public class MainActivity extends FlutterActivity {
    private static final String CHANNEL = "samples.flutter.io/battery";

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
                new MethodCallHandler() {
                    @Override
                    public void onMethodCall(MethodCall call, Result result) {
                        // TODO
                    }
                });
    }
}

然后,將下面的新方法添加到activity類中的,位于onCreate 方法下方:

private int getBatteryLevel() {
  int batteryLevel = -1;
  if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
    BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);
    batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
  } else {
    Intent intent = new ContextWrapper(getApplicationContext()).
        registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    batteryLevel = (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /
        intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
  }

  return batteryLevel;
}

最后,我們完成之前添加的onMethodCall方法。我們需要處理平臺方法名為getBatteryLevel,所以我們在call參數中進行檢測是否為getBatteryLevel。 這個平臺方法的實現只需調用我們在前一步中編寫的Android代碼,并使用response參數返回成功和錯誤情況的響應。如果調用未知的方法,我們也會通知返回:

@Override
public void onMethodCall(MethodCall call, Result result) {
    if (call.method.equals("getBatteryLevel")) {
        int batteryLevel = getBatteryLevel();

        if (batteryLevel != -1) {
            result.success(batteryLevel);
        } else {
            result.error("UNAVAILABLE", "Battery level not available.", null);
        }
    } else {
        result.notImplemented();
    }
}         

2.調用平臺通道

  static const platform = const MethodChannel('samples.flutter.io/battery');

  Future<Null> _getBatteryLevel() async {
    String batteryLevel;
    try {
      final int result = await platform.invokeMethod('getBatteryLevel');
      batteryLevel = 'Battery level at $result % .';
    } on PlatformException catch (e) {
      batteryLevel = "Failed to get battery level: '${e.message}'.";
    }
  }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,559評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,442評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,835評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,581評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,922評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,096評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,639評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,374評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,591評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,789評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,196評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,524評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,322評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,554評論 2 379

推薦閱讀更多精彩內容

  • Content: Flutter框架概況發展概述發展歷史框架特性框架結構 快速入門安裝Flutter在Mac OS...
    EchoZuo閱讀 6,482評論 3 54
  • 本篇為Flutter中文教程系列第一篇,先整體介紹一下Flutter,旨在讓您對Flutter有一個基本的認識。如...
    lazydu閱讀 12,765評論 2 38
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,737評論 25 708
  • 用兩張圖告訴你,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 12,812評論 2 59
  • 1 在單親家庭長大的小星,既不是那種能夠特別能吃苦、特別體諒媽媽的孩子,也不是那種不學無術、游手好閑的姑娘。 當初...
    羊小彩閱讀 1,198評論 0 1