flutter面试题(针对Android开发)

275 阅读7分钟

Flutter页面怎么使用原生页面

1、在 Flutter 项目中创建一个 AndroidView Widget,并指定原生视图的类型和参数。

2、(1)在 Android 项目中创建一个视图.这个view继承自PlatformView

(2)创建一个 FlutterViewFactory 类.实现 PlatformViewFactory 接口,在其中返回一个 PlatformView 实例,用于与 Flutter 通信

(3)写一个实现了FlutterPlugin的Plugin,里面注册这个视图工厂FlutterViewFactory

(4)在activity中flutterEngine.plugins.add(YourPlugin(this))


Future相关知识

Future表示一个指定类型的异步操作结果

.运行状态:会将这个函数放入队列等待执行并返回一个未完成的Future对象

.完成状态:当函数操作执行完成,Future对象就会携带一个值变成完成状态


await和then的区别

一般是有两种方式可以处理返回的结果,一种是await和async,一种是.then

共同点是:都是等待future执行完毕之后再去处理

区别:.then的方法是只等待当前future执行完后再去执行,而await是等待之前所有非异步的代码执行完成,并不单单只是当前的future


Stream和Future区别

Stream和Future都是用于接收异步事件数据,但是Future是表示单个计算结果的异步封装,而Stream表示的是多个序列化事件的异步封装

Stream可以接收多个异步操作的结果。 也就是说,在执行异步任务时,可以通过多次触发成功或失败事件来传递结果数据或错误异常。所以Stream常用于会多次读取数据的异步任务场景,如网络内容下载、文件读写


flutter屏幕适配方案(1、Flutter_screenutil2、从 SDK 层去修改(SDK版本适配问题))3、从应用层去修改

heapdump.cn/article/376…


Android跳转到Flutter页面

主要是通过FlutterActivity跳转,通过startActivity跳转,跳转指定界面时使用路由.比如

    startActivity(
       FlutterActivity
      .withNewEngine()
      .initialRoute("/setting")
      .build(activity!!))

.这样的话会启动慢,优化方法是在Application中提前初始化FlutterEngine 进行缓存   从缓存中取FlutterEngine进行启动.


Flutter跳转到Android页面

1、使用方法通道MethodChannel: • 在 Flutter 中创建一个 MethodChannel,并在该通道上发送消息给原生平台。

  • 在原生 Android 代码中接收消息,并执行相应的操作,例如启动一个新的 Activity

2、使用 PlatformView

  • 在原生 Android 中创建一个视图,并将其封装为 PlatformView。
  • 在 Flutter 中使用 AndroidView 或 UiKitView 来显示原生视图,并在需要时添加交互逻辑。

Flutter 跨组件传递数据

方式一:

InheritedWidget: 数据在Widget树中向下传递、共享.

定义一个便捷方法,方便子树中的widget获取共享数据 . 例如

    static **MyData** of(**BuildContext** context) {

    **return** context.dependOnInheritedWidgetOfExactType<**MyData**>();

  }

复写的updateShouldNotify中如果返回true,则子树中依赖 (build函数中有调用 )widget

    的子widgetstate.didChangeDependencies 会被调用

方式二:Notification: 数据流动方式是从子 Widget 向上传递至父 Widget.适用于子 Widget 状态变更,发送通知上报的场景.实现方式;如果想要实现自定义通知,我们首先需要继承 Notification 类实现一个通知类,然后widget调用这个通知类的dispatch方法分发通知,父widget通过NotificationListener监听通知.widget 布局中包含了子widget.

。Notification 类提供了 dispatch 方法,可以让我们沿着 context 对应的 Element 节点树向上逐层发送通知,父节点监听NotificationListener

方式三:事件总线EventBus

InheritedWidget 还是 Notificaiton都是在父子关系的 Widget 之间进行数据共享.

在没有这个关系的Widget中传递用EventBus.


flutter中的页面跳转: Navigator

1、最直接的页面跳转方式, 使用 MaterialPageRoute

    Navigator.push(

    context,

    MaterialPageRoute(builder: (context) => YourWidget()),

  );

2、具名的 Route

     MaterialApp(

   home: MyAppHome(), // becomes the route named '/'

   routes:   {

     '/a_route_name': (BuildContext context) => YourWidget(),

   },

 )

Navigator.pushNamed(context, '/a_route_name');

3、参数传递

(1)构造函数传递参数

**(2)命名路由传递参数:

     Navigator.pushNamed(

context,

'/second',

arguments: 'Hello Flutter',

);

在接收参数的页面中可以通过 ModalRoute.of(context).settings.arguments 获取参数值。

(3)全局状态管理,如 Provider

设置传出的参数

Navigator.pop(context, 'Yep!');

******** Flutter 页面生命周期


Flutter 页面生命周期就是 Flutter 页面组件 Widget 的生命周期 ;

页面的组件就是 StatefulWidget 组件 和 StatelessWidget 组件 ;

1、StatelessWidget 组件生命周期函数

StatelessWidget 组件生命周期函数 : 只有两个 , 分别是 createElement() , build() 两个方法 ;

2、StatefulWidget 组件生命周期函数

StatefulWidget 组件生命周期分为三组 :

① 初始化期 : createState , initState ;

② 更新期 : didChangeDependencies , build , didUpdateWidget ;

③ 销毁期 : deactivate , dispose ;

createState 函数 :

  • 所处时期 : 初始化期的生命周期函数
  • 调用时机 : 创建 StatefulWidget 之后调用的第一个方法 ;
  • 抽象方法 : 该方法是抽象方法 , 必须覆盖重写该方法 ;

initState 函数 : 所处时期 : 初始化期的生命周期函数

调用时机 : 该方法是创建 Widget 组件时除构造方法之外的第一个方法 ,

对应方法 : 对应 Android 中的 onCreate 方法 ; 

常用用法 : 在该方法中执行一些初始化操作 

didChangeDependencies 函数 :

  • 所处时期 : 更新期的生命周期函数 ;
  • 调用时机 : ① 创建 Widget 组件时 , 调用完 initState 方法后 , 调用该方法 ; ② InheritedWidget 相关 (若节点的父级结构中的层级 或 父级结构中的任一节点的widget类型有变化,节点会调用didChangeDependencies;若仅仅是父级结构某一节点的widget的某些属性值变化,节点不会调用didChangeDependencies)

build 函数 :

  • 所处时期 : 更新期的生命周期函数 ;
  • 调用时机 : ① 调用完 didChangeDependencies 方法后调用该方法 ; ② 调用 setState 方法之后 , 该方法也会被调用 ;
  • 方法作用 : 页面每次渲染时都会调用该方法 ;

didUpdateWidget 函数 :

所处时期 : 更新期的生命周期函数 ;

调用时机 : 该生命周期方法不经常调用 , 只有在父容器组件重绘时才调用该方法 ;(若节点调用setState方法,节点本身不会触发didUpdateWidget,此节点的子节点 会 调用didUpdateWidget)

方法机制 : 传入的 oldWidget 参数是旧的组件信息 , 将当前的 Widget 与旧的 Widget 进行对比 , 如果不相等 , 便执行额外操作 ;

deactivate 函数 :

  • 所处时期 : 销毁期的生命周期函数 ;
  • 调用时机 : 该生命周期方法不经常调用 , 只有在组件被移除时才调用 ;

dispose 函数 :

  • 所处时期 : 销毁期的生命周期函数 ;
  • 调用时机 : 组件被销毁时调用 , 要在该方法中进行资源的释放与销毁操作 ;

用户交互事件

1、指针事件

指针事件表示用户交互的原始触摸数据,其实就跟android的down、up等事件一样

2、手势识别: GestureDetector核心类,长按、拖动、双击之类的

3 Arena: 所有的指针事件都是通过Arena来进行处理的。Arena是一个管理指针事件的机制,它负责将事件分发给适当的接收者

Stream的两种订阅模式

在 Dart 中,Stream 有两种订阅模式:单订阅模式(Single-subscription)和广播模式(Broadcast)。

1、单订阅模式:

  • 使用 Stream 类创建的默认是单订阅模式的流。
  • 单订阅模式的流只能被一个订阅者(listener)订阅。
  • 订阅单订阅模式的流时,调用的是 listen 方法。
    Stream<int> singleSubscriptionStream() async* {
  yield* Stream.periodic(Duration(seconds: 1), (i) => i).take(5);
}

void main() {
  final stream = singleSubscriptionStream();
  stream.listen((data) => print(data)); // 单订阅模式的流只能被一个订阅者订阅
}

2、广播模式

  • 使用 StreamController 类创建的流可以选择是广播模式的流。
  • 广播模式的流可以被多个订阅者订阅。
  • 订阅广播模式的流时,调用的是 asBroadcastStream 方法。
    Stream<int> broadcastStream() async* {
  yield* Stream.periodic(Duration(seconds: 1), (i) => i).take(5);
}

void main() {
  final stream = broadcastStream().asBroadcastStream();
  stream.listen((data) => print('Listener 1: $data'));
  stream.listen((data) => print('Listener 2: $data')); // 可以有多个订阅者
}

Dart相关

`Dart` 中 number 类型分为 **intdouble ,没有 float 类型**