flutter 开发环境配置和生命周期学习

简介: flutter 开发环境配置和生命周期学习
配置环境
1. resolve.dependencies.gradle

Flutter安装目录/packages/flutter_tools/gradle/resolve.dependencies.gradle

maven {
url "https://maven.aliyun.com/repository/public/"
}
maven {
url "https://maven.aliyun.com/repository/central"
}
maven {
url "https://maven.aliyun.com/repository/google"
}

2. PUB_HOSTED_URL

https://pub.flutter-io.cn

3. PUB_CACHE 如果项目和flutterSDK不在同一盘符,就需要配置该变量,目录指向项目所在的盘符

D:\src\flutter_pub_cache

4. FLUTTER_STORAGE_BASE_URL

https://storage.flutter-io.cn


5. 终端代理命令

export https_proxy=http://127.0.0.1:7890 http_proxy=http://127.0.0.1:7890 all_proxy=socks5://127.0.0.1:7890

6. 其他
  1. xxx_android.iml 该文件可以让as 提示Open for Editing in Android Studio
  2. settings.gradle 定义了dev.flutter.flutter-gradle-plugin插件
生命周期
  • WidgetsBindingObserver(AppLifecycleState)
  • AppLifecycleListener
  • State
页面展示
  • 构造方法->initState->didChangeDependencies-build(到这一步页面展示出来了)
  • AppLifecycleState.resumed

前台切回后台

  • AppLifecycleState.inactive->AppLifecycleState.hidden
  • ->AppLifecycleState.paused
  • AppLifecycleListener.inactive->AppLifecycleListener.hide
  • ->AppLifecycleListener.pause
后台切回前台
  • AppLifecycleState.hidden->AppLifecycleState.inactive
  • ->AppLifecycleState.resumed
  • AppLifecycleListener.restart->AppLifecycleListener.show
  • ->AppLifecycleListener.resume
页面销毁
  • AppLifecycleState.inactive->AppLifecycleState.hidden->AppLifecycleState.paused->AppLifecycleState.detached->deactivate->dispose
  • AppLifecycleListener.hide->AppLifecycleListener.pause->AppLifecycleListener.detach

源码分析生命周期

ui的重绘都需要Widget的构建,也是就调用State.build或者StateLessWidget.build方法,

Element->markNeedsBuild-标记_dirty=true

调用Element.markNeedsBuild几个方法

  1. 开发者直接调用
    State.setState
  2. 修改依赖属性,会导致依赖发生变化

InheriteWidget-update-updated-notifyClients-notifyClient-dependent.didChangeDependencies

Eelement.didChangeDependencies

  1. StateFulElement.activate

ComponentElement.mount()->StatefulElement._firstBuild->state.initState()->state.didChangeDependencies()->rebuild()->StatefulElement.performRebuild()->第一次不会调用state.didChangeDependencies()因为_didChangeDependencies=fasle,后面会通过调用activited->state.activate()并且调用StatefulElement.didChangeDependencies()方法_didChangeDependencies = true


update->state.didUpdateWidget->rebuild->…


RenderObjectToWidgetElement->update->…

didUpdateWidget
  1. 自身state会导致自身build方法调用
  2. 父state会导致非const子组件的didUpdateWidget调用
didChangeDependencies
  1. InheritedWidget共享数据发生变化的时候
  2. 获取共享数据用到的context 对应的state的
  3. 通过父widget的setstate更新依赖的数据导致子组件的state.didChangeDependencies

BuildOwner通过StatefulElement间接驱动了state各个生命周期的触发

StatefulElement
class StatefulElement extends ComponentElement {
  StatefulElement(StatefulWidget widget)
      : _state = widget.createState(),
        super(widget) {
    state._element = this;
    state._widget = widget;
  }

  @override
  Widget build() => state.build(this);
  State<StatefulWidget> get state => _state!;
  State<StatefulWidget>? _state;

  @override
  void reassemble() {
    if (_debugShouldReassemble(_debugReassembleConfig, _widget)) {
      state.reassemble();
    }
    super.reassemble();
  }

  @override
  void _firstBuild() {
    assert(state._debugLifecycleState == _StateLifecycle.created);
    final Object? debugCheckForReturnedFuture = state.initState() as dynamic;
    state.didChangeDependencies();
    super._firstBuild();
  }

  @override
  void performRebuild() {
    if (_didChangeDependencies) {
      state.didChangeDependencies();
      _didChangeDependencies = false;
    }
    super.performRebuild();
  }

  @override
  void update(StatefulWidget newWidget) {
    super.update(newWidget);
    final Object? debugCheckForReturnedFuture = state.didUpdateWidget(oldWidget) as dynamic;
    rebuild(force: true);
  }

  @override
  void activate() {
    super.activate();
    markNeedsBuild();
  }

  @override
  void deactivate() {
    state.deactivate();
    super.deactivate();
  }

  @override
  void unmount() {
    super.unmount();
    state.dispose();
    state._element = null;
    _state = null;
  }

  @override
  InheritedWidget dependOnInheritedElement(Element ancestor, { Object? aspect }) {
    return super.dependOnInheritedElement(ancestor as InheritedElement, aspect: aspect);
  }

  bool _didChangeDependencies = false;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _didChangeDependencies = true;
  }

}
State
@optionalTypeArgs
class State {

  T get widget => _widget!;
  T? _widget;

  BuildContext get context {
    assert(() {
      if (_element == null) {
       
      }
      return true;
    }());
    return _element!;
  }
  StatefulElement? _element;

  bool get mounted => _element != null;

  @protected
  @mustCallSuper
  void initState() {
    assert(_debugLifecycleState == _StateLifecycle.created);
  }
  
  @mustCallSuper
  @protected
  void didUpdateWidget(covariant T oldWidget) { }

  
  @protected
  @mustCallSuper
  void reassemble() { }


  @protected
  void setState(VoidCallback fn) {
    assert(() {
      return true;
    }());
    final Object? result = fn() as dynamic;
    _element!.markNeedsBuild();
  }

  @protected
  @mustCallSuper
  void deactivate() { }

  @protected
  @mustCallSuper
  void activate() { }

  @protected
  @mustCallSuper
  void dispose() {
    assert(_debugLifecycleState == _StateLifecycle.ready);
    assert(() {
      _debugLifecycleState = _StateLifecycle.defunct;
      return true;
    }());
    if (kFlutterMemoryAllocationsEnabled) {
      MemoryAllocations.instance.dispatchObjectDisposed(object: this);
    }
  }

  @protected
  Widget build(BuildContext context);

  @protected
  @mustCallSuper
  void didChangeDependencies() { }
}

BuildOwner
class BuildOwner {
  
  BuildOwner({ this.onBuildScheduled, FocusManager? focusManager }) :
      focusManager = focusManager ?? (FocusManager()..registerGlobalHandlers());

 
  VoidCallback? onBuildScheduled;

  final _InactiveElements _inactiveElements = _InactiveElements();

  final List<Element> _dirtyElements = <Element>[];
  bool _scheduledFlushDirtyElements = false;

  bool? _dirtyElementsNeedsResorting;

 

  FocusManager focusManager;


  void scheduleBuildFor(Element element) {
   
    if (element._inDirtyList) {
      _dirtyElementsNeedsResorting = true;
      return;
    }
    if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
      _scheduledFlushDirtyElements = true;
      onBuildScheduled!();
    }
    _dirtyElements.add(element);
    element._inDirtyList = true;
  }

  void lockState(VoidCallback callback) {
    try {
      callback();
    } finally {
     
    }
  }

  
  @pragma('vm:notify-debugger-on-exception')
  void buildScope(Element context, [ VoidCallback? callback ]) {
    if (callback == null && _dirtyElements.isEmpty) {
      return;
    }
    if (!kReleaseMode) {
      Map<String, String>? debugTimelineArguments;
      FlutterTimeline.startSync(
        'BUILD',
        arguments: debugTimelineArguments
      );
    }
    try {
      _scheduledFlushDirtyElements = true;
      if (callback != null) {
       
        Element? debugPreviousBuildTarget;
        _dirtyElementsNeedsResorting = false;
        try {
          callback();
        } finally {
      
        }
      }
      _dirtyElements.sort(Element._sort);
      _dirtyElementsNeedsResorting = false;
      int dirtyCount = _dirtyElements.length;
      int index = 0;
      while (index < dirtyCount) {
        final Element element = _dirtyElements[index];
        final bool isTimelineTracked = !kReleaseMode && _isProfileBuildsEnabledFor(element.widget);
        if (isTimelineTracked) {
          Map<String, String>? debugTimelineArguments;
          FlutterTimeline.startSync(
            '${element.widget.runtimeType}',
            arguments: debugTimelineArguments,
          );
        }
        try {
          element.rebuild();
        } catch (e, stack) {
          
        }
        if (isTimelineTracked) {
          FlutterTimeline.finishSync();
        }
        index += 1;
        if (dirtyCount < _dirtyElements.length || _dirtyElementsNeedsResorting!) {
          _dirtyElements.sort(Element._sort);
          _dirtyElementsNeedsResorting = false;
          dirtyCount = _dirtyElements.length;
          while (index > 0 && _dirtyElements[index - 1].dirty) {   
            index -= 1;
          }
        }
      }
    } finally {
      for (final Element element in _dirtyElements) {
        element._inDirtyList = false;
      }
      _dirtyElements.clear();
      _scheduledFlushDirtyElements = false;
      _dirtyElementsNeedsResorting = null;
      if (!kReleaseMode) {
        FlutterTimeline.finishSync();
      }
     
    }
   
  }

 
  final Map<GlobalKey, Element> _globalKeyRegistry = <GlobalKey, Element>{};

  int get globalKeyCount => _globalKeyRegistry.length;

 
  void _registerGlobalKey(GlobalKey key, Element element) {
    _globalKeyRegistry[key] = element;
  }

  void _unregisterGlobalKey(GlobalKey key, Element element) {

    if (_globalKeyRegistry[key] == element) {
      _globalKeyRegistry.remove(key);
    }
  }



  @pragma('vm:notify-debugger-on-exception')
  void finalizeTree() {
    if (!kReleaseMode) {
      FlutterTimeline.startSync('FINALIZE TREE');
    }
    try {
      lockState(_inactiveElements._unmountAll); // this unregisters the GlobalKeys
    } catch (e, stack) {
    } finally {
      if (!kReleaseMode) {
        FlutterTimeline.finishSync();
      }
    }
  }
}
Element
class Element {
 Set<InheritedElement>? _dependencies;
 void markNeedsBuild() {
    assert(_lifecycleState != _ElementLifecycle.defunct);
    if (_lifecycleState != _ElementLifecycle.active) {
      return;
    }
    if (dirty) {
      return;
    }
    _dirty = true;
    owner!.scheduleBuildFor(this);
  }


  void rebuild({bool force = false}) {
    try {
      performRebuild();
    } finally {
      assert(() {
        owner!._debugElementWasRebuilt(this);
        assert(owner!._debugCurrentBuildTarget == this);
        owner!._debugCurrentBuildTarget = debugPreviousBuildTarget;
        return true;
      }());
    }
    assert(!_dirty);
  } 

  @protected
  @mustCallSuper
  void performRebuild() {
    _dirty = false;
  }
  
  @mustCallSuper
  void activate() {
    assert(_lifecycleState == _ElementLifecycle.inactive);
    assert(owner != null);
    final bool hadDependencies = (_dependencies != null && _dependencies!.isNotEmpty) || _hadUnsatisfiedDependencies;
    _dependencies?.clear();
    _hadUnsatisfiedDependencies = false;
    _updateInheritance();
    attachNotificationTree();
    if (_dirty) {
      owner!.scheduleBuildFor(this);
    }
    if (hadDependencies) {
      didChangeDependencies();
    }
  }
  @override
  InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object? aspect }) {
    _dependencies ??= HashSet<InheritedElement>();
    _dependencies!.add(ancestor);
    ancestor.updateDependencies(this, aspect);
    return ancestor.widget as InheritedWidget;
  }

  @override
  T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object? aspect}) {
    assert(_debugCheckStateIsActiveForAncestorLookup());
    final InheritedElement? ancestor = _inheritedElements == null ? null : _inheritedElements![T];
    if (ancestor != null) {
      return dependOnInheritedElement(ancestor, aspect: aspect) as T;
    }
    _hadUnsatisfiedDependencies = true;
    return null;
  }

  @override
  T? getInheritedWidgetOfExactType<T extends InheritedWidget>() {
    return getElementForInheritedWidgetOfExactType<T>()?.widget as T?;
  }
  
  
  
   @protected
  @pragma('vm:prefer-inline')
  Element? updateChild(Element? child, Widget? newWidget, Object? newSlot) {
    if (newWidget == null) {
      if (child != null) {
        deactivateChild(child);
      }
      return null;
    }

    final Element newChild;
    if (child != null) {
      bool hasSameSuperclass = true;
    
      assert(() {
        final int oldElementClass = Element._debugConcreteSubtype(child);
        final int newWidgetClass = Widget._debugConcreteSubtype(newWidget);
        hasSameSuperclass = oldElementClass == newWidgetClass;
        return true;
      }());
      if (hasSameSuperclass && child.widget == newWidget) {
        if (child.slot != newSlot) {
          updateSlotForChild(child, newSlot);
        }
        newChild = child;
      } else if (hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)) {
        if (child.slot != newSlot) {
          updateSlotForChild(child, newSlot);
        }
        final bool isTimelineTracked = !kReleaseMode && _isProfileBuildsEnabledFor(newWidget);
        if (isTimelineTracked) {
          Map<String, String>? debugTimelineArguments;
          Timeline.startSync(
            '${newWidget.runtimeType}',
            arguments: debugTimelineArguments,
          );
        }
        child.update(newWidget);
        if (isTimelineTracked) {
          Timeline.finishSync();
        }
        assert(child.widget == newWidget);
        assert(() {
          child.owner!._debugElementWasRebuilt(child);
          return true;
        }());
        newChild = child;
      } else {
        deactivateChild(child);
        assert(child._parent == null);
        newChild = inflateWidget(newWidget, newSlot);
      }
    } else {
      newChild = inflateWidget(newWidget, newSlot);
    }

    return newChild;
  }
  
    @mustCallSuper
  void update(covariant Widget newWidget) {
    assert(
      _lifecycleState == _ElementLifecycle.active
        && newWidget != widget
        && Widget.canUpdate(widget, newWidget),
    );
    _widget = newWidget;
  }

  @protected
  @pragma('vm:prefer-inline')
  Element inflateWidget(Widget newWidget, Object? newSlot) {
    final bool isTimelineTracked = !kReleaseMode && _isProfileBuildsEnabledFor(newWidget);
    if (isTimelineTracked) {
      Map<String, String>? debugTimelineArguments;
      FlutterTimeline.startSync(
        '${newWidget.runtimeType}',
        arguments: debugTimelineArguments,
      );
    }

    try {
      final Key? key = newWidget.key;
      if (key is GlobalKey) {
        final Element? newChild = _retakeInactiveElement(key, newWidget);
        if (newChild != null) {      
          try {
            newChild._activateWithParent(this, newSlot);
          } catch (_) {
            try {
              deactivateChild(newChild);
            } catch (_) {
              // Clean-up failed. Only surface original exception.
            }
            rethrow;
          }
          final Element? updatedChild = updateChild(newChild, newWidget, newSlot);
          assert(newChild == updatedChild);
          return updatedChild!;
        }
      }
      final Element newChild = newWidget.createElement();
      newChild.mount(this, newSlot);
      return newChild;
    } finally {
      if (isTimelineTracked) {
        FlutterTimeline.finishSync();
      }
    }
  }

}
ComponentElement
abstract class ComponentElement extends Element {
  
  ComponentElement(super.widget);

  Element? _child;

  bool _debugDoingBuild = false;
  @override
  bool get debugDoingBuild => _debugDoingBuild;

  @override
  void mount(Element? parent, Object? newSlot) {
    super.mount(parent, newSlot);
    _firstBuild();
    assert(_child != null);
  }

  void _firstBuild() {
    // StatefulElement overrides this to also call state.didChangeDependencies.
    rebuild(); // This eventually calls performRebuild.
  }
  
  @override
  @pragma('vm:notify-debugger-on-exception')
  void performRebuild() {
    Widget? built;
    try {
      built = build();
     
    } catch (e, stack) {
      _debugDoingBuild = false;
    } finally {
      super.performRebuild(); // clears the "dirty" flag
    }
    try {
      _child = updateChild(_child, built, slot);
      assert(_child != null);
    } catch (e, stack) {
      _child = updateChild(null, built, slot);
    }
  }
  @protected
  Widget build();

  @override
  void visitChildren(ElementVisitor visitor) {
    if (_child != null) {
      visitor(_child!);
    }
  }

  @override
  void forgetChild(Element child) {
    assert(child == _child);
    _child = null;
    super.forgetChild(child);
  }
}
ProxyElement InheritedElement

class ProxyElement{
  
  @override
  void update(ProxyWidget newWidget) {
    final ProxyWidget oldWidget = widget as ProxyWidget;
    assert(widget != newWidget);
    super.update(newWidget);
    assert(widget == newWidget);
    updated(oldWidget);
    rebuild(force: true);
  }
  @protected
  void updated(covariant ProxyWidget oldWidget) {
    notifyClients(oldWidget);
  } 
}


class InheritedElement{

  @override
  void notifyClients(InheritedWidget oldWidget) {
  
    for (final Element dependent in _dependents.keys) {
      assert(() {
        Element? ancestor = dependent._parent;
        while (ancestor != this && ancestor != null) {
          ancestor = ancestor._parent;
        }
        return ancestor == this;
      }());
      notifyDependent(oldWidget, dependent);
    }
  }
}









图片

build

createState

state.element = this

state.widget = widget

firstBuild

initState()

didChangeDipendcies


super.firstBuild->rebuild->performRebuild->didChangeDependencies->build


update->didUpdate->rebuild->performRebuild->didChangeDependencies->build

setState调用当前组件的build,调用子组件的update方法


setState->Element.markNeedsBuild->BuildOwner.scheduleBuildFor->


Element

bool _inDirtyList

bool _dirty 在下一次Vsync信号的时候会build


BuildOwner

List _dirtyElements

bool _scheduledFlushDirtyElements

buildScope rebuild


WidgetsBinding

_handleBuildScheduled->ensureVisualUpdate->scheduleFrame->PlatformDispatcher.scheduleFrame Vsync信号注册完成

drawFrame()->buildScope


SchedulerBinding

handleBeginFrame->PlatformDispatcher.onBeginFrame

handleDrawFrame->PlatformDispatcher.onDrawFrame

android 事件机制
  dispatcheTouchEvent->onInterceptTouchEvent->子控件
  
  接收到任务分发(diapatchTouchEvent)
  总经理->部门主管->员工
  
  拦截任务(onInterceptTouchEvent,只有viewgroup有这个方法,如果哪一级部门拦截就不会再向下一级部门分发)
  总经理->部门主管->员工
  
  //处理任务消耗(onTouchEvent true自己处理(包括后续事件MOVE UP),,false返回给上级处理)
  总经理->部门主管->员工
  
  //反馈处理结果
  总经理<-部门主管<-员工
  
  
  
  总经理收到任务并通知到最小员工,如果中间有部门拦截并处理,就不会向下传递,否则继续向下传递
  
  
  员工看是否有能力处理,如果有就处理,没有返回给上一级主管反馈情况

开发插件和package

1.修改pubspec.yaml文件 名字描述 版本 作者 github主页

2.reademe.md

3.LICENSE


检查

flutter packages pub publish --dry-run

发布

flutter packages pub publish


依赖包冲突

多个依赖都引用第三方依赖

直接在下面引用这个第三方依赖 优先级最高


打包存在多个一样的so文件,冲突

packagingOptions {

pickFirst ‘**/libstlport_shared.so’

}


相关文章
|
1月前
|
设计模式 移动开发 开发框架
如何学习 Flutter 框架?
学习 Flutter 需要耐心和持续的努力,通过系统的学习、实践、交流和不断跟进最新技术,你将逐渐掌握 Flutter 框架,并能够开发出高质量的移动应用。
|
1月前
|
存储 缓存 JavaScript
Flutter 学习之封装 WebView
【10月更文挑战第24天】通过以上的探讨,我们可以看出,在 Flutter 中封装 WebView 是非常有必要的,它可以提高代码的复用性、增强可维护性、提供统一接口。在实际应用中,我们需要根据具体的需求和场景,选择合适的封装方法和技术,以实现更好的效果。
|
2月前
|
Dart 开发者 Windows
flutter:dart的学习
本文介绍了Dart语言的下载方法及基本使用,包括在Windows系统上和VSCode中的安装步骤,并展示了如何运行Dart代码。此外,还详细说明了Dart的基础语法、构造函数、泛型以及库的使用方法。文中通过示例代码解释了闭包、运算符等概念,并介绍了Dart的新特性如非空断言操作符和延迟初始化变量。最后,提供了添加第三方库依赖的方法。
34 12
|
2月前
|
开发工具 Android开发 git
鸿蒙Flutter实战:01-搭建开发环境
本文介绍了如何搭建鸿蒙 Flutter 开发环境,包括安装 DevEco Studio 等工具,并详细说明了 Mac 和 Windows 系统下的环境变量配置。此外,还介绍了如何使用 FVM 管理多个 Flutter 版本,并提供了一些常见问题的解决方案和交流群信息。
134 0
鸿蒙Flutter实战:01-搭建开发环境
|
2月前
|
开发框架 UED 计算机视觉
flutter:图片&stful 生命周期 (三)
本文档介绍了如何在Flutter中处理图片,包括加载网络图片、本地图片、创建圆形图片和带有圆角的图片,以及如何配置`pubspec.yaml`文件来添加资源文件。还展示了如何使用`AssetImage`对象来显示本地资源图片,并通过代码示例详细说明了这些操作的实现方法。最后,简要介绍了StatefulWidget的生命周期。
|
3月前
|
Oracle Java 关系型数据库
Mac电脑上安装和配置Flutter开发环境
Mac电脑上安装和配置Flutter开发环境
65 3
|
3月前
|
Web App开发 开发工具 Android开发
【Flutter】Flutter安装和配置(mac)
【Flutter】Flutter安装和配置(mac)
|
4月前
|
开发框架 缓存 Android开发
Flutter相关痛点解决问题之研发环境与工程管理中的配置难题如何解决
Flutter相关痛点解决问题之研发环境与工程管理中的配置难题如何解决
|
4月前
|
Dart
Flutter笔记:手动配置VSCode中Dart代码自动格式化
Flutter笔记:手动配置VSCode中Dart代码自动格式化
572 5
|
4月前
|
XML 安全 Android开发
Flutter配置Android和IOS允许http访问
Flutter配置Android和IOS允许http访问
143 3
下一篇
DataWorks