Flutter 知識點總結

 MainAxisAlignment.spaceBetween
將主軸空白位置進行均分,排列子元素,首尾子控件距邊緣沒有間隙
MainAxisAlignment.spaceAround
將主軸空白區域均分,使中間各個子控件間距相等,首尾子控件距邊緣間距為中間子控件間距的一半
MainAxisAlignment.spaceEvenly
將主軸空白區域均分,使各個子控件間距相等

flutter column row布局的列表自適應寬高
mainAxisSize: MainAxisSize.min

通過runtimeType可以獲取當前數據類型
var e = [12.5,13.1];
print('e 的類型是: ${e.runtimeType}'); // e 的類型是: List<double>

flutter column嵌套listview不能滾動,或者不顯示的問題

因為 listview水平視口的寬度是無限的。
在listview外面嵌套一個expanded,或者一個container就可以了,尺寸計算的問題,expande就是listview有多大就有多大,container就是container多大listview就有多大,可以滾動

 child: Row(
          children: <Widget>[
            Expanded(
              child: ListView.builder(
                shrinkWrap: true,
                scrollDirection: Axis.horizontal,
                physics: BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
                itemCount: 120,
                itemBuilder: (context, index) => Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: new Text('${index}'),
                ),
              ),
            ),
          ],
        ),

List 常見用法


   List<dynamic> topTitles = ['審批單', '機票列表', '客服'];
    //遍歷list
    for(var value intopTitles){
      print("---------<>---${value}");
    }
    topTitles.forEach((item) => {print(item)});


//遍歷得到一個新的List  用此方法 亦可動態加載Widget
   List<dynamic>   newList = topTitles.map((item) {
      return item + "111";
    }).toList();


//list的map方法不能獲取index  用Asmap  轉換成map 后
//動態加載Widget

        Row(
                children: topTitles
                    .asMap()
                    .keys
                    .map((index) => Expanded(
                          flex: 1,
                          child: Column(
                            children: <Widget>[Text(topTitles[index])],
                          ),
                        ))
                    .toList(),
              ),



Map


    //遍歷map
 mostCare.forEach((k, v) {
      // print(k + "==" + v.toString()); //類型不一樣的時候就toString()
    });



//map   key遍歷生成Widget
 Row(
                children: mostCare.keys.map((key) {
                  //  print('-----key--${key}');
                  return Expanded(
                    flex: 1,
                    child: Column(
                      children: <Widget>[Text(mostCare[key])],
                    ),
                  );
                }).toList(),
              ),

延遲

/*    //延遲3秒
    Future.delayed(Duration(seconds: 3), () {
     
    });*/

軟鍵盤彈出頂掉內容、防止鍵盤超出屏幕

研究了半天發現十分簡單,只需兩行代碼。布局中最外層包裹一個SingleChildScrollView組件,然后在Scaffold里增加一個屬性 resizeToAvoidBottomPadding: false,即刻解決鍵盤遮擋問題,
類似于 Android 中的 android:windowSoftInputMode=”adjustResize”,控制界面內容 body 是否重新布局來避免底部被覆蓋了,比如當鍵盤顯示的時候,重新布局避免被鍵盤蓋住內容。默認值為 true。

Flutter TextField 光標和內容不能對齊問題

添加該屬性
TextField(
    style: TextStyle(textBaseline: TextBaseline.alphabetic),
)

flutter中text設置overflow還是會超出屏幕解決方法

使用flex控件代替row控件,并且在文字外面包一層Expanded
,應該是橫向row沒有確定寬度,text根據內容來撐開row,所以就會超出,換成flex 使text最大寬度能占用剩下的所有寬度,所以達到最寬的時候就會顯示省略號。
這個錯誤就好像再column中使用listView一樣,會出現一個在無限高度的view中使用listView的錯誤,

屏幕適配原理

flutter_screenutil:

說一下適配方案, 比如我們設計師設計的UI是根據Iphone6來做的,我們知道 iPhone6的分辨率是750*1334(px)、

又或者是根據hdpi的設備來設計的UI,我們知道hdpi的 Android設備是 (240 dpi),像素密度是1.5,即hdpi設備的分辨率寬度是320px, 總之,無論設計稿的單位是px,或者是dp,我們都能夠轉換成px.
那么我們如果根據px來適配,ios和 android 就都可以兼容了.
假設,我們的設計稿手機是10801920 px.
設計稿上有一個540960 的組件, 即寬度和寬度是手機的一半. 如果我們直接寫的時候組件的尺寸這么定義,在其他尺寸的設備上未必是一半,或多,或少. 但是我們可以按比例來看,即我們要實現的寬度是實際設備的一半.
那么假設我們設備的寬度是deviceWidth和deviceHeight , 我們要寫的組件大小為: 寬:(540/1080)deviceWidth,高度: (960/1920)deviceHeight.
通過這個公式我們可以發現,我們要寫的組件寬度就是設計稿上的尺寸width(deviceWdith/原型設備寬度).那么每次我們寫ui的時候,只要直接哪來設計稿的尺寸(deviceWdith/設備原型)寬度即可
原理就是先獲取,實際設備與原型設備的尺寸比例.

構造方法

如果沒有自定義構造方法,則會有個默認構造方法
如果存在自定義構造方法 默認構造方法將失效
構造方法不能重載

命名構造方法
使用命名構造方法 可以實現多個構造方法
使用 類名.方法 的形式實現

class Person {
    string name
    int age
    final string sex
    /**
     * 這里 使用this的語法糖可以對final類型賦值
     * 但是寫在構造方法中就不行了,因為執行在構造方法之前
     */
    Person (string name ,this.age ,this.sex) { // 第二種是語法糖,
        this.name = name
        print(age)
    }
}

var per = new Person('jack', 20)

---------------------------------------
命名構造方法
class Person {
    string name
    int age
    final string sex

    Person (string name ,this.age ,this.sex) { // 第二種是語法糖,
        this.name = name
        print(age)
    }
    Person.withName(string name) {
        this.name = name
    }
}
<!-- 多個構造方法 類似oc -->
new Person('jack', 12, 'man')
new Person.withName('marry')

混合 mixins (with)

除了繼承和接口實現之外,Dart 還提供了另一種機制來實現類的復用,即“混入”(Mixin)。通過混入,一個類里可以以非繼承的方式使用其他類中的變量與方法,效果正如你想象的那樣。

混合的對象是類
可以混合多個

生命周期

State 的生命周期可以分為 3 個階段。
State 初始化時會依次執行 :構造方法 -> initState -> didChangeDependencies -> build,隨后完成頁面渲染。
Widget 的狀態更新,主要由 3 個方法觸發:setStState、didchangeDependencies 與 didUpdateWidget。
Widget 組件銷毀相對比較簡單,系統會調用 deactivate 和 dispose 這兩個方法,來移除或銷毀組件。

Widget 渲染過程

  • Widget、是控件實現的基本邏輯單位,里面存儲的是有關視圖渲染的配置信息,包括布局、渲染屬性、事件響應信息等。
  • Element :是 Widget 的一個實例化對象,它承載了視圖構建的上下文數據,是連接結構化的配置信息到完成最終渲染的橋梁。
  • RenderObject 、主要負責實現視圖渲染的對象、通過控件樹中的每個控件創建不同類型的渲染對象,組成渲染對象樹。

Fluttter 將視圖樹的概念進行了擴展,把視圖數據的組織和渲染抽象為三部分,即 Widget,Element 和 RenderObject。
渲染對象樹在 Flutter 的展示過程分為四個階段,即布局、繪制、合成和渲染。
布局和繪制在 RenderObject 中完成,Flutter 采用深度優先機制遍歷渲染對象樹,確定樹中各個對象的位置和尺寸,并把它們繪制到不同的圖層上,布局和繪制完成后,再交給 Skia進行合成和渲

為什么需要增加中間的這層 Element 樹呢?直接由 Widget 命令 RenderObject 去干活兒不好嗎?

因為 Widget 具有不可變性,但 Element 卻是可變的,實際上,Element 樹這一層將 Widget 樹的變化(類似 React 虛擬 DOM diff)做了抽象,可以只將真正需要修改的部分同步到真實的 RenderObject 樹中,最大程度降低對真實渲染視圖的修改,提高渲染效率,而不是銷毀整個渲染視圖樹重建。

合成和渲染

隨著頁面越來越復雜、Flutter 的渲染樹層級很多,直接交付給渲染引擎進行多圖層渲染,可能會出現大量渲染內容的重復繪制,所以還需要先進行一次圖層合成,即將所有的圖層根據大小、層級、透明度等規則計算出最終的顯示效果,將相同的圖層歸類合并,簡化渲染樹,提高渲染效率,合并完成后,Flutter 會將幾何圖層數據交由 Skia 引擎加工成二維圖像數據,最終交由 GPU 進行渲染,完成界面的展示。

StatelessWidget與StatefulWidget區別

分別是組裝控件的容器
StatelessWidget 不帶綁定狀態,而 StatefulWidget 帶綁定狀態,其依賴的數據在 Widget 生命周期中可能會頻繁地發生變化,由 State創建視圖,數據驅動視圖更新。

單線程模型

 // 聲明了一個延遲 3 秒返回的 Hello Flutter   的 Future,
    Future<String> fetchContent() async {
      await Future.delayed(new Duration(seconds: 3));
      return 'Hello Flutter';
    }

    /**在Dart中,有await標記的運算,其結果值都是一個Future對象,
     * 對于異步函數返回的 Future 對象,如果調用者決定同步等待, 則需要在調用處使用 await 關鍵字,
     * 并且在調用處的函數體使用 async 關鍵字。
     * Dart 中的 await 并不是阻塞等待,而是異步等待,Dart 會將調用體的函數也視作異步函數,
     * 將等待語句的上下文放入 Event Queue 中,一旦有了結果,Event Loop 就會把它從 Event Queue 中取出,等待代碼繼續執行。
     */
    //await 與 async 有效區間只對調用上下文的函數有效,并不向上傳遞


    testAwaitAndAsync() async {
      String data = await fetchContent();
      print('-----${data}-----');  //等待3秒后打印Hello Flutter   然后打印123
      print('----123------');
    }

Event Loop 完整版的流程圖
在 Dart 中,實際上有兩個隊列,一個事件隊列(Event Queue),另一個則是微任務隊列(Microtask Queue)。在每一次事件循環中,Dart 總是先去第一個微任務隊列中查詢是否有可執行的任務,如果沒有,才會處理后續的事件隊列的流程。


Isolate

Dart 也提供了多線程機制,即 Isolate。在 Isolate 中,資源隔離做得非常好,每個 Isolate 都有自己的 Event Loop 與 Queue,Isolate 之間不共享任何資源,只能依靠消息機制通信,因此也就沒有資源搶占問題。

Isolate 通過發送管道(SendPort)實現消息通信機制。我們可以在啟動并發 Isolate 時將主 Isolate 的發送管道作為參數傳給它,這樣并發 Isolate 就可以在任務執行完畢后利用這個發送管道給我們發消息了。
,在 Isolate 中,發送管道是單向的:我們啟動了一個 Isolate 執行某項任務,Isolate 執行完畢后,發送消息告知我們。如果 Isolate 執行任務時,需要依賴主 Isolate 給它發送參數,執行完畢后再發送執行結果給主 Isolate,這樣雙向通信的場景我們如何實現呢?答案也很簡單,讓并發 Isolate 也回傳一個發送管道即可。

跨組件通訊

Flutter 與 Android iOS 原生的通信有以下三種方式

BasicMessageChannel 實現 Flutter 與 原生(Android 、iOS)雙向通信 ,主要是傳遞字符串json等數據和一些半結構體的數據,
MethodChannel 實現 Flutter 與 原生原生(Android 、iOS)雙向通信, 用于傳遞方法調用
EventChannel 實現 原生原生(Android 、iOS)向Flutter 發送消息 ,用于數據流(event streams)的通信

平臺視圖 Flutter端使用原生視圖

Flutter 提供了一個平臺視圖(Platform View)的概念。它提供了一種方法,允許開發者在 Flutter 里面嵌入原生系統(Android 和 iOS)的視圖

  • 首先,由作為客戶端的 Flutter,通過向原生視圖的 Flutter 封裝類(在 iOS 和 Android 平臺分別是 UIKitView 和 AndroidView)傳入視圖標識符,用于發起原生視圖的創建請求;
  • 然后,原生代碼側將對應原生視圖的創建交給平臺視圖工廠(PlatformViewFactory)實現;
  • 最后,在原生代碼側將視圖標識符與平臺視圖工廠進行關聯注冊,讓 Flutter 發起的視圖創建請求可以直接找到對應的視圖創建工廠。

class SampleView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //使用Android平臺的AndroidView,傳入唯一標識符sampleView
    if (defaultTargetPlatform == TargetPlatform.android) {
      return AndroidView(viewType: 'sampleView');
    } else {
      //使用iOS平臺的UIKitView,傳入唯一標識符sampleView
      return UiKitView(viewType: 'sampleView');
    }
  }
}

我們分別創建了平臺視圖工廠和原生視圖封裝類,并通過視圖工廠的 create 方法,將它們關聯起來


//視圖工廠類
class SampleViewFactory extends PlatformViewFactory {
    private final BinaryMessenger messenger;
    //初始化方法
    public SampleViewFactory(BinaryMessenger msger) {
        super(StandardMessageCodec.INSTANCE);
        messenger = msger;
    }
    //創建原生視圖封裝類,完成關聯
    @Override
    public PlatformView create(Context context, int id, Object obj) {
        return new SimpleViewControl(context, id, messenger);
    }
}
//原生視圖封裝類
class SimpleViewControl implements PlatformView {
    private final View view;//緩存原生視圖
    //初始化方法,提前創建好視圖
    public SimpleViewControl(Context context, int id, BinaryMessenger messenger) {
        view = new View(context);
        view.setBackgroundColor(Color.rgb(255, 0, 0));
    }
    
    //返回原生視圖
    @Override
    public View getView() {
        return view;
    }
    //原生視圖銷毀回調
    @Override
    public void dispose() {
    }
}


protected void onCreate(Bundle savedInstanceState) {
  ...
  Registrar registrar =    registrarFor("samples.chenhang/native_views");//生成注冊類
  SampleViewFactory playerViewFactory = new SampleViewFactory(registrar.messenger());//生成視圖工廠

registrar.platformViewRegistry().registerViewFactory("sampleView", playerViewFactory);//注冊視圖工廠
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,208評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,746評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,666評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,477評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,960評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,200評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,726評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,617評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,807評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,049評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,425評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,674評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,432評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,769評論 2 372

推薦閱讀更多精彩內容