技术摘要2

209 阅读5分钟

Swift与OC

Swift和OC的优缺点

  • Swift中struct和class有什么区别?
    struct是值引用,更轻量,存放于栈区,class是类型引用,存放于堆区。struct无法继承,class可继承。
  • Swift和OC枚举的区别:
    OC:
    1.oc的枚举值相当于这个文件中的一个局部变量,只能是整型
    2.不同枚举中,枚举名称不可以一样,在同一文件
    swift:
    3.枚举里可以写方法
    4.枚举的rawValue可以是Float(float也是赋值的后面依次+1)或是String,或是没有
    5.可以用Rank(rawValue: 3)方法创建一个枚举实例

OC、Swift混编并使用pod模块化的那些坑与解决方案

  • 同一个pod里Swift可以直接调用OC,但是OC调用Swift时需要把权限设为public
  • 用Swift时NCClassFromString的参数要用 bundle.className, bundle就是pod名或者主项目名

Flutter

Flutter面试题

Flutter优缺点

  • 优点
    热重载(Hot Reload),利用Android Studio直接一个ctrl+s就可以保存并重载,模拟器立马就可以看见效果,相比原生冗长的编译过程强很多;
    一切皆为Widget的理念,对于Flutter来说,手机应用里的所有东西都是Widget,通过可组合的空间集合、丰富的动画库以及分层课扩展的架构实现了富有感染力的灵活界面设计;
    借助可移植的GPU加速的渲染引擎以及高性能本地代码运行时以达到跨平台设备的高质量用户体验。简单来说就是:最终结果就是利用Flutter构建的应用在运行效率上会和原生应用差不多。
  • 缺点
    不支持热更新;
    三方库有限,需要自己造轮子;
    Dart语言编写,增加了学习难度,并且学习了Dart之后无其他用处,相比JS和Java来说;

StatefullWidget生命周期

  • initState():Widget 初始化当前 State,在当前方法中是不能获取到 Context 的,如想获取,可以试试 Future.delayed()
  • didChangeDependencies():在 initState() 后调用,State对象依赖关系发生变化的时候也会调用。
  • deactivate():当 State 被暂时从视图树中移除时会调用这个方法,页面切换时也会调用该方法,和Android里的 onPause 差不多。
  • dispose():Widget 销毁时调用。
  • didUpdateWidget:Widget 状态发生变化的时候调用。

Widgets、RenderObjects 和 Elements的关系

  • Widget :仅用于存储渲染所需要的信息。
  • RenderObject :负责管理布局、绘制等操作。
  • Element :才是这颗巨大的控件树上的实体。 Widget会被inflate(填充)到Element,并由Element管理底层渲染树。Widget并不会直接管理状态及渲染,而是通过State这个对象来管理状态。Flutter创建Element的可见树,相对于Widget来说,是可变的,通常界面开发中,我们不用直接操作Element,而是由框架层实现内部逻辑。就如一个UI视图树中,可能包含有多个TextWidget(Widget被使用多次),但是放在内部视图树的视角,这些TextWidget都是填充到一个个独立的Element中。Element会持有renderObject和widget的实例。记住,Widget 只是一个配置,RenderObject 负责管理布局、绘制等操作。

在第一次创建 Widget 的时候,会对应创建一个 Element, 然后将该元素插入树中。如果之后 Widget 发生了变化,则将其与旧的 Widget 进行比较,并且相应地更新 Element。重要的是,Element 不会被重建,只是更新而已。

Flutter 是如何与原生Android、iOS进行通信的?

Flutter 通过 PlatformChannel 与原生进行交互,其中 PlatformChannel 分为三种:

  • BasicMessageChannel :用于传递字符串和半结构化的信息。
  • MethodChannel :用于传递方法调用(method invocation)。
  • EventChannel : 用于数据流(event streams)的通信。 同时 Platform Channel 并非是线程安全的 .

Future和Stream

  • Future
    Dart 在单线程中是以消息循环机制来运行的,其中包含两个任务队列,一个是“微任务队列” microtask queue,另一个叫做“事件队列” event queue。
    在Java并发编程开发中,经常会使用Future来处理异步或者延迟处理任务等操作。而在Dart中,执行一个异步任务同样也可以使用Future来处理。在 Dart 的每一个 Isolate 当中,执行的优先级为 :Main > MicroTask > EventQueue。
  • Stream
    在Dart中,Stream 和 Future 一样,都是用来处理异步编程的工具。它们的区别在于,Stream 可以接收多个异步结果,而Future 只有一个。
    Stream 的创建可以使用 Stream.fromFuture,也可以使用 StreamController 来创建和控制。还有一个注意点是:普通的 Stream 只可以有一个订阅者,如果想要多订阅的话,要使用 asBroadcastStream()。

Flutter启动过程

runApp(MyApp()):

1、 WidgetsFlutterBinding.ensureInitialized

  负责初始化一个WidgetsBinding的全局单例,WidgetsFlutterBinding混合了GestureBinding, SchedulerBinding, ServicesBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding

  • GestureBinding:提供了window.onPointerDataPacket 回调,绑定Framework手势子系统,是Framework事件模型与底层事件的绑定入口。
  • ServicesBinding:提供了window.onPlatformMessage 回调, 用于绑定平台消息通道(message channel),主要处理原生和Flutter通信。
  • SchedulerBinding:提供了window.onBeginFramewindow.onDrawFrame回调,监听刷新事件,绑定Framework绘制调度子系统。
  • PaintingBinding:绑定绘制库,主要用于处理图片缓存。
  • SemanticsBinding:语义化层与Flutter engine的桥梁,主要是辅助功能的底层支持。
  • RendererBinding: 提供了window.onMetricsChangedwindow.onTextScaleFactorChanged等回调。它是渲染树与Flutter engine的桥梁。
  • WidgetsBinding:提供了window.onLocaleChangedonBuildScheduled 等回调。它是Flutter widget层与engine的桥梁。
2、 WidgetsFlutterBinding.attachRootWidgetWidgetsBinding

紧接着会调用WidgetsBinding的attachRootWidget方法,该方法负责将根Widget添加到RenderView上.

void attachRootWidget(Widget rootWidget) {
  _renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
    container: renderView, 
    debugShortDescription: '[root]',
    child: rootWidget
  ).attachToRenderTree(buildOwner, renderViewElement);
}

renderView是一个RenderObject,它是渲染树的根,而renderViewElementrenderView对应的Element对象,可见该方法主要完成了根widget到根 RenderObject再到根Element的整个关联过程

3、 WidgetsFlutterBinding.scheduleWarmUpFrame(SchedulerBinding)

回到runApp的实现中,当调用完attachRootWidget后,最后一行会调用 WidgetsFlutterBinding 实例的 scheduleWarmUpFrame() 方法,该方法的实现在SchedulerBinding 中,它被调用后会立即进行一次绘制(而不是等待"vsync" 信号),在此次绘制结束前,该方法会锁定事件分发,也就是说在本次绘制结束完成之前Flutter将不会响应各种事件.