国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Flutter原理篇:GestureDetector原理深度剖析及手勢原理(上)

這篇具有很好參考價值的文章主要介紹了Flutter原理篇:GestureDetector原理深度剖析及手勢原理(上)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

今天我們來講講GestureDetector的深度剖析,只有了解原理了,才能知道手勢沖突如何解決以及如何更靈活的運用手勢。
我們先來看看GestureDetector的內(nèi)部結(jié)構(gòu)

Flutter原理篇:GestureDetector原理深度剖析及手勢原理(上),flutter

1.GestureDetector只是一個包裝類,最終還是由ListenerRenderPointListener執(zhí)行事件的操作

2.點擊事件開始時會首先執(zhí)行RawGestureDetector_handlePointDown方法。

//GestureDetector
class GestureDetector extends StatelessWidget {
  Widget build(BuildContext context) {
	if (onTapDown != null ||
        onTapUp != null ||
        .....
    ) {
      //包裝相關(guān)的手勢類(單擊手勢)
      gestures[TapGestureRecognizer] = GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(..........
        },
      );
    }
    if (onDoubleTap != null ||
        onDoubleTapDown != null ||
        onDoubleTapCancel != null
        .....
    ) {
      //包裝相關(guān)的手勢類(雙擊手勢)
gestures[DoubleTapGestureRecognizer]=GestureRecognizerFactoryWithHandlers<DoubleTapGestureRecognizer>(..........
        },
      );
    }
    ........
	return RawGestureDetector(
      gestures: gestures,
      behavior: behavior,
      excludeFromSemantics: excludeFromSemantics,
      child: child,
    );
}

//RawGestureDetector的state方法
class RawGestureDetectorState extends State<RawGestureDetector> {
  @override
  void initState() {
    super.initState();
    _semantics = widget.semantics ?? _DefaultSemanticsGestureDelegate(this);
    _syncAll(widget.gestures);
  }
  void _syncAll(Map<Type, GestureRecognizerFactory> gestures) {
  	//手勢保存
    final Map<Type, GestureRecognizer> oldRecognizers = _recognizers!;
    _recognizers = <Type, GestureRecognizer>{};
    //遍歷新手勢,過濾舊手勢。gestures是從GestureDetector傳過來的新手勢
    for (final Type type in gestures.keys) {
      //如果是舊的手勢(oldRecognizers[type])跟新手勢一樣,就直接賦值
      //如果舊手勢跟新手勢不一樣,則需要調(diào)用舊手勢的構(gòu)造函數(shù)并執(zhí)行初始化方法。
      _recognizers![type] = oldRecognizers[type] ?? gestures[type]!.constructor();
      gestures[type]!.initializer(_recognizers![type]!);
    }
    //對舊手勢執(zhí)行dispose()方法進(jìn)行銷毀。
    for (final Type type in oldRecognizers.keys) {
      if (!_recognizers!.containsKey(type)) {
        oldRecognizers[type]!.dispose();
      }
    }
  }
   @override
  Widget build(BuildContext context) {
  	//RawGestureDetector最終調(diào)用的是Listener,Listener才是重點需要關(guān)注的。
    Widget result = Listener(
      onPointerDown: _handlePointerDown,
      onPointerPanZoomStart: _handlePointerPanZoomStart,
      behavior: widget.behavior ?? _defaultBehavior,
      child: widget.child,
    );
    return result;
  }
}
//Listener的類
class Listener extends SingleChildRenderObjectWidget {
  @override
  RenderPointerListener createRenderObject(BuildContext context) {
    //主要的手勢類,重點關(guān)注這個RenderPointerListener
    return RenderPointerListener(
      onPointerDown: onPointerDown,
      onPointerMove: onPointerMove,
      .......
      behavior: behavior,
    );
  }
}

abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
   //...省略100字
}

abstract class GestureRecognizer extends 
GestureArenaMember with DiagnosticableTreeMixin {
   //...省略100字
}

在點擊事件進(jìn)來時,事件的傳遞流程梳理

1.每個傳進(jìn)來的手勢都會被打包成GestureRecognizer的相關(guān)子類,OneSequenceGestureRecognizer是我們最常用的子類,同時它也是眾多子類的父類。

2.打包好的GestureRecognizer相關(guān)子類會緩存到RawGestureDetectorgestures變量中以供后面手勢加入競技場和競爭的時候使用到
3.RawGestureDetector每一次的初始化的時候都會對gestures列表進(jìn)行更新,始終保持最新的緩存

4.這個RenderPointerListener是Listener的renderObject,這個類間接繼承了HitTestTarget接口,其實所有的renderObject都實現(xiàn)了HitTestTarget這個接口。顧名思義,單擊測試目標(biāo)。后面手勢競爭的時候都會對實現(xiàn)HitTestTarget的實例進(jìn)行單擊測試。

5.GestureRecognizer同時也繼承了GestureArenaMember(競技成員),所以子類也可以看作是競技成員

下圖是GestureRecognizer的部分繼承關(guān)系

Flutter原理篇:GestureDetector原理深度剖析及手勢原理(上),flutter

  //RenderPointerListener(RenderObject)
  @override
  void handleEvent(PointerEvent event, HitTestEntry entry) {
    assert(debugHandleEvent(event, entry));
    if (event is PointerDownEvent) {
      //這里執(zhí)行的就是上圖的_handlePointDown方法
      return onPointerDown?.call(event);
    }
    if (event is PointerMoveEvent) {
      return onPointerMove?.call(event);
    }
    if (event is PointerUpEvent) {
      return onPointerUp?.call(event);
    }
    ....
  }

小結(jié):這一部分主要講述了手勢事件如何封裝成GestureRecognizer,并最終走到RenderPointerListenerhandleEvent對手勢類進(jìn)行處理進(jìn)行處理。在此之前我們先看看GestureBinding的初始化監(jiān)聽。對于后面的手勢競爭有非常大的幫助。

mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, HitTestTarget {
  //創(chuàng)建手勢競技場(負(fù)責(zé)決出競技勝者)
  final GestureArenaManager gestureArena = GestureArenaManager();
  //創(chuàng)建目標(biāo)收集類(負(fù)責(zé)收集單擊測試目標(biāo))
  final Map<int, HitTestResult> _hitTests = <int, HitTestResult>{};

  
}
//手勢競技場
class GestureArenaManager {
  //管理不同的成員管理類
  final Map<int, _GestureArena> _arenas = <int, _GestureArena>{};
}
//手勢競技成員管理
class _GestureArena {
  //每個成員管理類都持有一個競技成員列表,即上面說的GestureRecognizer啦
  final List<GestureArenaMember> members = <GestureArenaMember>[];
  bool isOpen = true;
  bool isHeld = false;
}

Flutter原理篇:GestureDetector原理深度剖析及手勢原理(上),flutter

1.我們最初在main類中執(zhí)行runApp()方法的時候,就開始對GestureBinding。的相關(guān)監(jiān)聽進(jìn)行初始化

2.同時創(chuàng)建手勢競技場GestureArenaManager負(fù)責(zé)管理不同的競技場,每個競技場又管理者不同的GestureArenaMember的成員

3.同時創(chuàng)建了目標(biāo)收集器_hitTests針對不同的事件類型創(chuàng)建不同的HitTestResult(這就是真正的目標(biāo)收集器,即收集實現(xiàn)了HitTestTarget接口的RenderObjectGestureBinding)單擊測試目標(biāo)收集器

4.注意,GestureBinding也是實現(xiàn)了HitTestTarget的單擊目標(biāo)測試,同上面所說的RenderObject一樣會接受單擊目標(biāo)測試。

5.GestureBinding實現(xiàn)了_handlePointerEventImmediately這個方法,由androidios監(jiān)聽事件并傳入,對事件進(jìn)行進(jìn)一步的處理。

手勢處理主要分兩個階段
1.目標(biāo)收集
2.手勢競爭

一、目標(biāo)收集

//GestureBinding的實現(xiàn),監(jiān)聽底層收到的事件進(jìn)行相關(guān)處理并傳輸
  void _handlePointerEventImmediately(PointerEvent event) {
    HitTestResult? hitTestResult;
    if (event is PointerDownEvent || event is PointerSignalEvent || event is PointerHoverEvent || event is PointerPanZoomStartEvent) {
      //創(chuàng)建一個目標(biāo)收集器。一般事件開始的時候都會先走這個,這是第一步。
      hitTestResult = HitTestResult();
      //單擊測試,收集可以響應(yīng)單機(jī)測試的實例
      hitTestInView(hitTestResult, event.position, event.viewId);
      if (event is PointerDownEvent || event is PointerPanZoomStartEvent) {
      	//存儲單擊測試結(jié)果,后面可以使用到
        _hitTests[event.pointer] = hitTestResult;
      }
    } else if (event is PointerUpEvent || event is PointerCancelEvent || event is PointerPanZoomEndEvent) {
      //移除本次事件
      hitTestResult = _hitTests.remove(event.pointer);
    } else if (event.down || event is PointerPanZoomUpdateEvent) {
      //其他類型的down事件,取出單擊測試的結(jié)果(通過單擊測試的實例)
      hitTestResult = _hitTests[event.pointer];
    }
    if (hitTestResult != null ||
        event is PointerAddedEvent ||
        event is PointerRemovedEvent) {
       //分配事件給通過單擊測試的實例(hitTestResult)
      dispatchEvent(event, hitTestResult);
    }
  }

  //RendererBinding
  @override
  void hitTestInView(HitTestResult result, Offset position, int viewId) {
 	//在RenderBinding中又調(diào)用了renderView的hitTest
    _viewIdToRenderView[viewId]?.hitTest(result, position: position);
    //這里最后才會調(diào)用GestureBinding的hitTestInView
    super.hitTestInView(result, position, viewId);
  }
  bool hitTest(HitTestResult result, { required Offset position }) {
    if (child != null) {
      //這里又開始觸發(fā)子節(jié)點的hitTest
      child!.hitTest(BoxHitTestResult.wrap(result), position: position);
    }
    //最后將自身即根renderview加入單擊測試結(jié)果
    result.add(HitTestEntry(this));
    return true;
  }
  //子節(jié)點的單擊測試方法
  bool hitTest(BoxHitTestResult result, { required Offset position }) {
  	//這里判斷單擊的position是否在_size的范圍內(nèi)(就是是否在子節(jié)點的范圍內(nèi))
    if (_size!.contains(position)) {
      if (hitTestChildren(result, position: position) || hitTestSelf(position)) {
      	//子節(jié)點在此刻通過了單擊測試,即在點擊范圍內(nèi),則加入到result中。
        result.add(BoxHitTestEntry(this, position));
        return true;
      }
    }
    return false;
  }
//開始事件分發(fā)
void dispatchEvent(PointerEvent event, HitTestResult? hitTestResult) {
    if (hitTestResult == null) {
      try {
      	//hitTestResult為null說明是可能回調(diào)了
      	//PointerHoverEvent,PointerAddedEvent,PointerRemovedEvent
      	//由路由分發(fā)出去
        pointerRouter.route(event);
      } catch (exception, stack) {
      
    for (final HitTestEntry entry in hitTestResult.path) {
      try {
      	//執(zhí)行所有目標(biāo)收集到的單擊測試實例的handleEvent方法。
        entry.target.handleEvent(event.transformed(entry.transform), entry);
      } catch (exception, stack) {
        
      }
    }
  }
//GestureDetector實現(xiàn)的RenderPointerListener(調(diào)用子節(jié)點的handleEvent)
void handleEvent(PointerEvent event, HitTestEntry entry) {
    assert(debugHandleEvent(event, entry));
    if (event is PointerDownEvent) {
      return onPointerDown?.call(event);
    }
    if (event is PointerMoveEvent) {
      return onPointerMove?.call(event);
    }
    //省略一萬字....
}

Flutter原理篇:GestureDetector原理深度剖析及手勢原理(上),flutter

目標(biāo)收集流程

1.當(dāng)事件下發(fā)到GestureBinding時,會分別對不同事件進(jìn)行判斷處理,其中有手勢點擊和手勢抬起事件

2.當(dāng)進(jìn)入PointerDownEvent的時候,先進(jìn)入Rendview根節(jié)點的hitTest方法調(diào)用hitTestChildren進(jìn)行子節(jié)點遍歷,判斷子節(jié)點是否符合點擊范圍,如果符合則將自身加入hitTestResult單擊測試列表中

3.當(dāng)遍歷完子節(jié)點后再單擊測試Rendview根節(jié)點,只有hitTestSelf條件符合了才能將自身加入到單擊測試列表hitTestResult中。

4.最后一步再將GestureBinding加入到單擊測試列表中,因為GestureBinding也實現(xiàn)了HitTestTarget單擊測試目標(biāo)接口。都會進(jìn)行測試。

5.當(dāng)單擊目標(biāo)測試完成后,將進(jìn)行事件分發(fā),分發(fā)到各個RendObject(都實現(xiàn)了HitTestTarget方法)中,即調(diào)用每個實例的handleEvent方法。

6.handleEvent的第一次點擊即PointerDownEvent終會執(zhí)行RawGestureDetector的_handlePointerDown方法


至此,目標(biāo)收集流程已經(jīng)結(jié)束,現(xiàn)在開始事件競爭

二、手勢競爭

手勢收集完成后,就進(jìn)入到了RawGestureDetector的_handlePointerDown方法

void _handlePointerDown(PointerDownEvent event) {
    assert(_recognizers != null);
    //這是對前面我們收集的競技成員進(jìn)行遍歷訪問
    for (final GestureRecognizer recognizer in _recognizers!.values) {
      //給每個競技成員跟蹤點擊事件
      recognizer.addPointer(event);
    }
  }
}
void addPointer(PointerDownEvent event) {
    _pointerToKind[event.pointer] = event.kind;
    if (isPointerAllowed(event)) {
      addAllowedPointer(event);
    } else {
      handleNonAllowedPointer(event);
    }
  }
}
//由子類OneSequenceGestureRecognizer(這個比較常用)
void addAllowedPointer(PointerDownEvent event) {
    //開始跟蹤事件處理
    startTrackingPointer(event.pointer, event.transform);
  }
}
@protected
  void startTrackingPointer(int pointer, [Matrix4? transform]) {
    //省略部分代碼...
    _entries[pointer] = _addPointerToArena(pointer);
  }
//在這里開始將當(dāng)前的GestureArenaMember(就是上面的Recognizer)添加到競技場gestureArena
GestureArenaEntry _addPointerToArena(int pointer) {
    if (_team != null) {
      return _team!.add(pointer, this);
    }
    return GestureBinding.instance.gestureArena.add(pointer, this);
  }

Flutter原理篇:GestureDetector原理深度剖析及手勢原理(上),flutter

1._recognizers最初在初始化的時候已經(jīng)對不同的事件進(jìn)行手勢封裝成GestureRecognizer的不同子類,現(xiàn)在就是開始用的時候了

2.往下走最終調(diào)用_addPointerToArena方法,即將GestureRecognizer的子類實現(xiàn)添加到GestureBindinggestureArena手勢競技場中進(jìn)行手勢競爭。

三、?決出最終勝者

由于目標(biāo)收集中最后一個加入的是GestureBinding,所以GestureBinding也是實現(xiàn)了HitTestTarget接口

@override // from HitTestTarget
  void handleEvent(PointerEvent event, HitTestEntry entry) {
    pointerRouter.route(event);
    if (event is PointerDownEvent || event is PointerPanZoomStartEvent) {
      //關(guān)閉競技場
      gestureArena.close(event.pointer);
    } else if (event is PointerUpEvent || event is PointerPanZoomEndEvent) {
      //清理競技場
      gestureArena.sweep(event.pointer);
    } else if (event is PointerSignalEvent) {
      pointerSignalResolver.resolve(event);
    }
  }
//關(guān)閉競技場(只是做個標(biāo)記)
void close(int pointer) {
    final _GestureArena? state = _arenas[pointer];
    if (state == null) {
      return; // This arena either never existed or has been resolved.
    }
    state.isOpen = false;
    _tryToResolveArena(pointer, state);
  }
//決出競技場最終的勝者
void _tryToResolveArena(int pointer, _GestureArena state) {
    if (state.members.length == 1) {
      //只有一個成員,決出勝者
      scheduleMicrotask(() => _resolveByDefault(pointer, state));
    } else if (state.members.isEmpty) {
      //沒有成員,則移除當(dāng)前手勢的競技場
      _arenas.remove(pointer);
    } else if (state.eagerWinner != null) {
      //只有一個勝者,直接宣布獲勝
      _resolveInFavorOf(pointer, state, state.eagerWinner!);
    }
  }
void _resolveByDefault(int pointer, _GestureArena state) {
    if (!_arenas.containsKey(pointer)) {
      return; // This arena has already resolved.
    }
    final List<GestureArenaMember> members = state.members;
    _arenas.remove(pointer);
    //取第一個作為勝者
    state.members.first.acceptGesture(pointer);
  }

1.前面子類GestureRecognizer添加進(jìn)競技場之后,在GestureBinding開始決出勝者,即可以響應(yīng)點擊事件的成員。

2.在競技場關(guān)閉的時候開始決出勝者,也是事件開始的事件即PointerDownEvent事件,開始決策

3.手勢成員只有一個的時候,直接取第一個手勢為勝者,手勢成員為空的時候,直接清理競技場,手勢成員已經(jīng)有勝者的時候,直接確定競技場勝者

void sweep(int pointer) {
    final _GestureArena? state = _arenas[pointer];
    if (state == null) {
      //競技場為空直接返回。
      return;
    }
    assert(!state.isOpen);
    if (state.isHeld) {
      //競技場被掛起,直接返回。一般是雙擊的時候會用到這個掛起
      state.hasPendingSweep = true;
      return; 
    }
    //移除競技場
    _arenas.remove(pointer);
    //競技場成員不為空
    if (state.members.isNotEmpty) {
      // First member wins.
      //直接取第一個成員作為勝者并調(diào)用其的acceptGesture
      state.members.first.acceptGesture(pointer);
      // 其他的敗者則調(diào)用rejectGesture
      for (int i = 1; i < state.members.length; i++) {
        state.members[i].rejectGesture(pointer);
      }
    }
  }

Flutter原理篇:GestureDetector原理深度剖析及手勢原理(上),flutter

只要競技場沒有被掛起或為空,且此時會有多個手勢競技成員,這時候會取第一個成員作為勝者,就是renderbox最里面的那個。下節(jié)重點講解雙擊事件以及事件的靈活運用。文章來源地址http://www.zghlxwxcb.cn/news/detail-859776.html

到了這里,關(guān)于Flutter原理篇:GestureDetector原理深度剖析及手勢原理(上)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Flutter 筆記 | Flutter 核心原理(三)布局(Layout )過程

    Flutter 筆記 | Flutter 核心原理(三)布局(Layout )過程

    Layout(布局)過程主要是確定每一個組件的布局信息(大小和位置),F(xiàn)lutter 的布局過程如下: 父節(jié)點向子節(jié)點傳遞約束(constraints)信息,限制子節(jié)點的最大和最小寬高。 子節(jié)點根據(jù)約束信息確定自己的大?。╯ize)。 父節(jié)點根據(jù)特定布局規(guī)則(不同布局組件會有不同的布

    2024年02月09日
    瀏覽(18)
  • 深入理解 Flutter 圖片加載原理

    深入理解 Flutter 圖片加載原理

    作者:京東零售 徐宏偉 來源:京東云開發(fā)者社區(qū) 隨著Flutter穩(wěn)定版本逐步迭代更新,京東APP內(nèi)部的Flutter業(yè)務(wù)也日益增多,F(xiàn)lutter開發(fā)為我們提供了高效的開發(fā)環(huán)境、優(yōu)秀的跨平臺適配、豐富的功能組件及動畫、接近原生的交互體驗,但隨之也帶來了一些OOM問題,通過線上監(jiān)控

    2024年02月12日
    瀏覽(22)
  • Flutter 的線程模型和異步原理

    Flutter 的線程模型和異步原理

    本文字?jǐn)?shù):: 36130 字 預(yù)計閱讀時間: 91 分鐘 在 Android 應(yīng)用中, 用戶時常會遇到界面卡頓的情況,非常影響用戶的體驗。作為 Android 開發(fā)肯定都知道:應(yīng)用在主線程里做了大量的耗時操作(例如文件讀寫, 數(shù)據(jù)庫讀寫,網(wǎng)絡(luò)訪問,圖片編解碼等),就會導(dǎo)致 UI 不能及時刷新,

    2024年02月15日
    瀏覽(15)
  • Flutter筆記:Web支持原理與實踐

    Flutter筆記:Web支持原理與實踐

    Flutter筆記 Web支持原理與實踐 作者 : 李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 郵箱 : 291148484@163.com CSDN:https://blog.csdn.net/qq_28550263/article/details/135037756 華為開發(fā)者社區(qū):https://bbs.huaweicloud.com/blogs/418443 一個純 Flutter 構(gòu)建的 Web 示例站點(建設(shè)中): Flutter-Online Top http://

    2024年01月23日
    瀏覽(28)
  • Flutter視圖原理之StatefulWidget,InheritedWidget

    Flutter視圖原理之StatefulWidget,InheritedWidget

    在flutter項目中,StatelessWidget,StatefulWidget,InheritedWidget是常見的widget,今天通過源碼分析下它們是怎么實現(xiàn)的。 對應(yīng)的功能基本上都是在element中實現(xiàn)的,widget只是提供組件配置的作用,所以在講解StatefulWidget,InheritedWidget的時候,主要還是分析對應(yīng)的element的實現(xiàn)。 StatefulW

    2024年02月07日
    瀏覽(20)
  • SWD下載調(diào)試接口原理深度剖析

    SWD下載調(diào)試接口原理深度剖析

    由于我們公司自己需要開發(fā)燒錄工具,本人通過google搜相關(guān)文檔和看ARM公司的技術(shù)文檔,終于實現(xiàn)了這個功能。該篇幅敢很自信的說把SWD理論講的最淺顯易懂的。 作為ARM嵌入式工程師,下載調(diào)試器都應(yīng)該知道,但你真正了解SWD如何下載調(diào)試的么?ARM 芯片通過什么物理接口和

    2023年04月24日
    瀏覽(12)
  • 深入理解 Flutter 圖片加載原理 | 京東云技術(shù)團(tuán)隊

    深入理解 Flutter 圖片加載原理 | 京東云技術(shù)團(tuán)隊

    隨著Flutter穩(wěn)定版本逐步迭代更新,京東APP內(nèi)部的Flutter業(yè)務(wù)也日益增多,F(xiàn)lutter開發(fā)為我們提供了高效的開發(fā)環(huán)境、優(yōu)秀的跨平臺適配、豐富的功能組件及動畫、接近原生的交互體驗,但隨之也帶來了一些OOM問題,通過線上監(jiān)控信息和Observatory工具結(jié)合分析我們發(fā)現(xiàn)問題的原因

    2024年02月12日
    瀏覽(19)
  • 深度剖析動態(tài)規(guī)劃算法:原理、優(yōu)勢與實戰(zhàn)

    動態(tài)規(guī)劃是一種優(yōu)化技術(shù),通常用于解決那些可以分解為子問題的問題。它的核心思想是將大問題分解成小問題,通過解決小問題來構(gòu)建大問題的解。這種方法通常用于解決最優(yōu)化問題,其中目標(biāo)是找到最佳解決方案,通常是最大化或最小化某個值。 動態(tài)規(guī)劃算法的核心原理

    2024年02月07日
    瀏覽(22)
  • Flutter 狀態(tài)管理框架 Provider 和 Get 原理分析

    Flutter 狀態(tài)管理框架 Provider 和 Get 原理分析

    首先,為什么需要狀態(tài)管理,這是因為 Flutter 基于?聲明式?構(gòu)建 UI ,使用狀態(tài)管理的目的之一就是解決「聲明式」開發(fā)帶來的問題。 「聲明式」開發(fā)是一種區(qū)別于傳原生的方式,所以我們沒有在原生開發(fā)中聽到過狀態(tài)管理,如何理解「聲明式」開發(fā)呢? 「聲明式」VS「命令

    2023年04月24日
    瀏覽(43)
  • TensorFlow Lite,ML Kit 和 Flutter 移動深度學(xué)習(xí):6~11

    TensorFlow Lite,ML Kit 和 Flutter 移動深度學(xué)習(xí):6~11

    原文:Mobile Deep Learning with TensorFlow Lite, ML Kit and Flutter 協(xié)議:CC BY-NC-SA 4.0 譯者:飛龍 本文來自【ApacheCN 深度學(xué)習(xí) 譯文集】,采用譯后編輯(MTPE)流程來盡可能提升效率。 不要擔(dān)心自己的形象,只關(guān)心如何實現(xiàn)目標(biāo)?!对瓌t》,生活原則 2.3.c 認(rèn)證是任何應(yīng)用中最突出的

    2023年04月24日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包