赞
踩
extension ... on
为String定义一个扩展类extension StringExt on String{ // 2. 扩展方法 int add(int x, int y){ return x + y; } } void mian(){ String str = 'hello'; // 3. 使用扩展类方法 int result = str.add(3, 7); debugPrint(result.toString()); } // 单元测试 import 'package:flutter_start/extTest.dart'; import 'package:flutter_test/flutter_test.dart'; void main(){ test('StringExt', (){ String ext = 'ext'; expect(ext.add(3, 7), 10); }); }
单继承
Dart中使用Mixins
,可以达到多继承的效果
继承自Object
,不能继承其他类不能有构造函数
多个mixins类
// 类D 继承A和B 关键字 with class D extends A with B{ } // mixin 的使用 class A { String info="this is A"; void printA(){ print("A"); } void run(){ print("A Run"); } } class B { void printB(){ print("B"); } void run(){ print("B Run"); } } class C extends Person with B,A{ C(String name, num age) : super(name, age); }
后面的类中的方法将前面的类中相同的方法覆盖
消息循环机制
Future就是将任务插入到事件队列
Future.microtask()
scheduleMicrotask()
Stream
中的执行异步的模式就是scheduleMicrotask
。因为microtask的优先级又高于event。所以,如果 microtask 太多
就可能会对触摸、绘制等外部事件造成阻塞卡顿
。
Stream 有同步流和异步流
之分。它们的区别在于同步流
会在执行 add,addError 或 close 方法时立即向流的监听器 StreamSubscription 发送事件,而异步流
总是在事件队列中的代码执行完成后在发送事件。`
Stream分为Single Subscription和Broadcast两种类型, 前者只允许订阅(listen)一次,后者允许多次订阅。
单订阅在订阅者出现之前会持有数据,在订阅者出现之后就才转交给它。
广播订阅可以同时有多个订阅者,当有数据时就会传递给所有的订阅者,而不管当前是否已有订阅者存在。
会报错,单订阅只能有一次订阅.
即使取消了第一个监听器,也不允许在单订阅流上设置其他的监听器。
Stream 可以通过 transform() 方法(返回另一个 Stream)进行连续调用。
通过 Stream.asBroadcastStream() 可以将一个单订阅模式的 Stream 转换成一个多订阅模式的 Stream,isBroadcast 属性可以判断当前 Stream 所处的模式。
Dart是单线程模型
。
主要依赖dart的并发编程(Isolate)、异步和事件驱动机制
Isolate.spawn
方法获取一个新的Isolate对象,两个Isolate之间使用SendPort相互发送消息
,而Isolate中也存在了一个与之对应ReceivePort
接收消息用来处理,但是我们需要注意的是SendPort
和ReceivePort
在每一个Isolate都有一对,只有同一个Isolate中的ReceivePort才能接受当前类的SendPort发送的消息并且处理。@override void initState() async { super.initState(); // 主Isolate的ReceivePort ReceivePort receivePort = ReceivePort(); SendPort? otherSendPort; // 主Isolate接收到子Isolate中由主Isolate的SendPort发送过来的消息 receivePort.listen((message) { if(message is SendPort){ otherSendPort = message; }else{ // 处理消息 // ...... // 子Isolate的SendPort在主Isolate中向子Isolate发送消息 otherSendPort?.send('我是来自主Isolate的消息'); } }); // 创建子Isolate Isolate isolate = await Isolate.spawn((message) { // message 是主Isolate的SendPort // 在子Isolate中创建一个新的ReceivePort ReceivePort recPort = ReceivePort(); // 主Isolate的SendPort SendPort? mainSendPort; // 运用主Isolate的SendPort将子Isolate的SendPort发送给主Isolate message.send(recPort.sendPort); // 子Isolate监听接收到主Isolate那边发送的消息 谁发送?子Isolate的SendPort recPort.listen((msg) { if(msg is SendPort){ mainSendPort = msg; }else{ // 主Isolate的SendPort向主Isolate发送消息 mainSendPort?.send('我是来自子Isolate的消息'); } }); }, receivePort.sendPort);// 参数二 将主Isolate的SendPort传递给子Isolate }
await for是用来不断获取stream流中的数据,然后执行循环体中的操作。它一般用在直到stream什么时候完成,并且必须等待传递完成后才能使用,不然会阻塞。
Stream<String> stream = new Stream<String>.fromIterable(['1', '2', '3','4']);
main() async{
await for(String s in stream){
print(s);
}
}
会
Flutter只关心向 GPU提供视图数据,GPU的 VSync信号同步到 UI线程,UI线程使用 Dart来构建抽象的视图结构,这份数据结构在 GPU线程进行图层合成,视图数据提供给 Skia引擎渲染为 GPU数据,这些数据通过 OpenGL或者 Vulkan提供给 GPU。
widget是用于描述Element配置信息的,flutter中一切都是widget,尺寸、颜色、组件等都是widget
element是widget树上特定位置的实例
renderobject是渲染上的一个对象
依赖关系:Element树依赖Widget树,渲染树依赖Element树,最终的UI树是由独立的Element节点构成。
一个widget会创建一个element
一个element持有一个widget和render object,element
会对比widget的变化,将那写需要更新和重建的widget,同步到render object树,以最小的开销来渲染
setState()执行后,会执行build()
app的状态:AppLifecycleState
inactive
:活跃可见
paused
:关闭或者切换到后台时,不可见的状态
hidden
:后台运行状态
resumed
:切回到前台可见状态
detached
:关闭状态
Flutter SDK 3.13 之前的方式: with WidgetsBindingObserver
在initState()
中注册 WidgetsBinding.instance.addObserver(this);
在dispose()
移除 WidgetsBinding.instance.removeObserver(this);
在didChangeAppLifecycleState()
回调中,检测app的状态
Flutter SDK 3.13 之后的方式:AppLifecycleListener
late final AppLifecycleListener _listener; @override void initState() { super.initState(); // Initialize the AppLifecycleListener class and pass callbacks _listener = AppLifecycleListener( onStateChange: _onStateChanged, ); } @override void dispose() { // Do not forget to dispose the listener _listener.dispose(); super.dispose(); } // Listen to the app lifecycle state changes void _onStateChanged(AppLifecycleState state) { switch (state) { case AppLifecycleState.detached: _onDetached(); case AppLifecycleState.resumed: _onResumed(); case AppLifecycleState.inactive: _onInactive(); case AppLifecycleState.hidden: _onHidden(); case AppLifecycleState.paused: _onPaused(); } }
createState
:可以调用多次
class _MyWidgetState extends State<MyWidget> { @override void initState() { super.initState(); // 在 State 对象被插入树中时调用,这个方法只会被调用一次。 } @override void didChangeDependencies() { super.didChangeDependencies(); // 在 initState 之后调用,表示 State 对象的依赖关系发生变化。 } @override Widget build(BuildContext context) { // 在此构建 Widget 树 return Container(); } @override void didUpdateWidget(MyWidget oldWidget) { super.didUpdateWidget(oldWidget); // 当父 Widget 重建时调用。 // 如果父 Widget 重建时需要重新配置子 Widget,则会调用此方法。 } @override void deactivate() { // 在此处理 State 对象从树中被移除的操作 super.deactivate(); } @override void activate() { // 在此处理 State 对象被重新插入树里 super.activate(); } @override void dispose() { // 当 State 对象被永久从树中移除时调用 super.dispose(); } } // 打开页面执行:initState、didChangeDependencies // 关闭页面执行:deactivate、dispose
class MyWidget extends StatefulWidget {
@override
Widget build(BuildContext context) {
return Widget;
}
}
setState()过程主要工作是记录所有的脏元素,会引起build函数执行,更新widget树、更新Element树和RenderObject树,最后重新渲染。
StatelessWidget 没有要管理的内部状态.
无状态widget的build方法通常只会在以下三种情况调用:
StatefullWidget是可变状态的widget。 使用setState方法管理StatefulWidget的状态的改变。调用setState告诉Flutter框架,某个状态发生了变化,Flutter会重新运行build方法,以便应用程序可以应用最新状态。
报错,但不影响布局;会报生命周期创建错误;
PlatformChannel
BasicMessageChannel :用于传递字符串和半结构化的信息。
MethodChannel :用于传递方法调用(method invocation)。
EventChannel : 用于数据流(event streams)的通信。
// 1. 创建java类。 实现FlutterPlugin和MethodCallHandler public class MsaOaidPlugin implements FlutterPlugin, MethodCallHandler{ @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { Log.e("---------","==========onAttachedToEngine"); channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "msa_oaid"); channel.setMethodCallHandler(this); this.context = flutterPluginBinding.getApplicationContext(); System.loadLibrary("msaoaidsec"); } @Override public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { Log.e("---------","==========onMethodCall"); if(call.method.equals("isSupport")){ new DemoHelper().getDeviceIds(context, new IIdentifierListener() { @Override public void onSupport(IdSupplier idSupplier) { result.success(idSupplier.isSupported()); } }); }else if(call.method.equals("getOaid")){ new DemoHelper().getDeviceIds(context, new IIdentifierListener() { @Override public void onSupport(IdSupplier idSupplier) { result.success(idSupplier.getOAID()); } }); }else{ result.notImplemented(); } } @Override public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { channel.setMethodCallHandler(null); Log.e("---------","==========onDetachedFromEngine"); } } // 2. flutter lib包下创建dart类 class MsaOaid { static const MethodChannel _channel = MethodChannel('msa_oaid'); static Future<bool> isSupport() async { final bool support = await _channel.invokeMethod('isSupport'); return support; } static Future<String?> getOaid() async { final String? oaid = await _channel.invokeMethod('getOaid'); return oaid; } }
我整理了一套Android面试题合集,除了以上面试题,还包含【Java 基础、集合、多线程、虚拟机、反射、泛型、并发编程、Android四大组件、异步任务和消息机制、UI绘制、性能调优、SDN、第三方框架、设计模式、Kotlin、计算机网络、系统启动流程、Dart、Flutter、算法和数据结构、NDK、H.264、H.265.音频编解码、FFmpeg、OpenMax、OpenCV、OpenGL ES】
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。