29个Flutter面试问题移动开发人员需要知道的

作为下一轮革命,Flutter正在移动市场中蓬勃发展。事实证明,它具有赢得所有移动技术的潜力,并成为未来跨平台应用程序开发的唯一选择。跟随并检查第一个最全面的Flutter面试问答列表,该列表将在2020年的移动开发人员面试中发展。FullStack.Cafe独家提供。

最初发布在FullStack.Cafe-开发人员的真实技术面试问答

Q1:什么是Flutter?

主题:颤振
难度:⭐

Flutter是Google提供的一个开源UI工具包,用于通过单个代码库为桌面,Web和移动设备制作精美的,本机编译的应用程序。 Flutter应用是使用Dart编程语言构建的。

?资料来源:flutter.dev

Q2:什么是Dart?为什么Flutter使用它?

主题:颤振
难度:⭐⭐

Dart是一种面向对象的垃圾收集编程语言,可用于开发Flutter应用程序。
它也是由Google创建的,但是是开源的,并且在Google内部和外部都有社区。
由于以下原因,Dart被选为Flutter的语言:

  • Dart是AOT(提前时间)编译为快速,可预测的本机代码,几乎所有Flutter都可以用Dart编写。这不仅使Flutter更快,而且几乎所有内容(包括所有小部件)都可以自定义。
  • Dart还可以通过JIT(Just In Time)进行编译,以实现异常快速的开发周期和改变游戏规则的工作流程(包括Flutter流行的亚秒级有状态热重装)。
  • Dart允许Flutter避免使用像JSX或XML这样的声明式布局语言,也不需要单独的可视界面构建器,因为Dart的声明式程序化布局易于阅读和可视化。而且,由于所有布局都以一种语言和一种位置显示,因此Flutter可以轻松地提供使布局变得轻松的高级工具。

?资料来源:hackernoon.com

Q3:什么是“小部件”并在Flutter中提及其重要性?

主题:颤振
难度:⭐⭐

  • 小部件基本上是Flutter中的UI组件。
  • 这是描述元素配置的一种方式。
  • 它们是受React中组件启发的。

小部件在Flutter中很重要,因为Flutter应用程序中的所有内容都是小部件,从简单的“文本”到“按钮”再到“屏幕布局”。

?资料来源:stackoverflow.com

Q4:Flutter中有几种类型的小部件?

主题:颤振
难度:⭐⭐

有两种类型的小部件:

  1. StatelessWidget:不需要可变状态的小部件。
  2. StatefulWidget:具有可变状态的小部件。

?资料来源:proandroiddev.com

Q5:Flutter中的“ main()”和“ runApp()”函数有什么区别?

主题:颤振
难度:⭐⭐

  • main () 函数来自类似Java的语言,因此它是所有程序启动的地方,没有它,即使没有UI也无法在Flutter上编写任何程序。
  • runApp() 函数应返回将附加到屏幕上的小部件,作为将要呈现的小部件树的根。

?资料来源:stackoverflow.com

Q6:什么是应用程序状态?

主题:颤振
难度:⭐⭐

  • 非短暂状态,您要在应用程序的许多部分之间共享,以及希望在用户会话之间保持的状态,就是我们所说的应用程序状态(有时也称为共享状态)。
  • 应用状态示例:
    • 用户偏好
    • 登录信息
    • 社交网络应用中的通知
    • 电子商务应用程序中的购物车
    • 新闻应用中文章的已读/未读状态

?资料来源:flutter.dev

Q7:Flutter中有哪些不同的构建模式?

主题:颤振
难度:⭐⭐

  • Flutter工具在编译应用程序时支持三种模式,以及用于测试的无头模式。
  • 您可以根据您在开发周期中的位置来选择编译模式。
  • 这些模式是:
    • 除错
    • 轮廓
    • 发布

?资料来源:flutter.dev

Q8:区分StatelessWidget和StatefulWidget?

主题:颤振
难度:⭐⭐⭐

无状态:窗口小部件状态仅创建一次,然后可以更新值,但不能显式声明状态。这就是为什么它只有一个类 StatelessWidget。他们永远都无法重跑 build() 再次的方法。

有状态的:小部件可以在事件触发后多次更新其STATE(本地)和值。这就是原因,实现方式也有所不同。在这里,我们有2个类,一个是 StatefulWidget &另一个是状态执行处理程序,即 State。所以如果我说,他们可以重新运行 build() 再次基于触发的事件进行方法。

  • 一种 StatelessWidget 永远不会自行重建(但可以从外部事件重建)。一种 StatefulWidget 能够。
  • 一种 StatelessWidget 是静态的 StatefulWidget 是动态的。

请参见下图:

?资料来源:stackoverflow.com

Q9:为什么我们将函数传递给小部件?

主题:颤振
难度:⭐⭐⭐

  • 函数是Dart中的一流对象,可以作为参数传递给其他函数。
  • 我们将一个函数传递给一个小部件,本质上说,“发生某些事情时调用此函数”。
  • 使用Android(

Java函数是Dart中的一流对象,可以作为参数传递给其他函数。

button.setOnClickListener(new View.OnClickListener() {  
    @override  
    public void onClick(View view) {  
      // Do something here  
    }  
  }  
);

(请注意,这仅是用于设置侦听器的代码。定义按钮需要单独的XML代码。)

飞镖等效项:

FlatButton(  
  onPressed: () {  
    // Do something here  
  }  
)

(Dart同时进行声明和设置回调。)
这变得更加整洁有序,并帮助我们避免不必要的复杂化。

?资料来源:medium.com

Q10:区分热重启和热重启吗?

主题:颤振
难度:⭐⭐⭐

热装

  • Flutter热重装功能与命令提示符或终端上的Small r键组合使用。
  • 热重装功能可以快速编译文件中新添加的代码,并将代码发送到Dart虚拟机。更新完Code Dart虚拟机后,请使用小部件更新应用程序UI。
  • 热重启所需的时间少于热重启所需的时间。
  • Hot Reload也有一个缺点,如果您在应用程序中使用状态,则Hot Reload将保留状态,这样它们就不会在Hot Reload上更新为默认值。

热重启

  • 热重启与热重新加载有很大不同。
  • 在热重启中,它会破坏保留状态值并将其设置为默认值。因此,如果您在应用程序中使用“状态”值,则在每次热重启后,开发人员都会获取完全编译的应用程序,并且所有状态都将设置为其默认值。
  • 应用窗口小部件树已使用新键入的代码完全重建。
  • 热重启所需的时间比热重启所需的时间长得多。

?资料来源:https://flutter-examples.com/difference-between-hot-reload-and-hot-restart-in-flutter-dart/

问题11:在Dart中区分必需参数和可选参数吗?

主题:颤振
难度:⭐⭐⭐

必要参数

Dart必需参数是传递给函数的参数,而函数或方法需要所有这些参数来完成其代码块。

findVolume(int length, int breath, int height) {
 print('length = $length, breath = $breath, height = $height');
}

findVolume(10,20,30);

可选参数

  • 可选参数在任何必需参数之后的参数列表末尾定义。
  • 在Flutter / Dart中,有3种可选参数:
    • 命名
      • 由参数盘点 { }
      • 例如。 getUrl(int color, [int favNum])
    • 位置性
      • 由参数盘点 [ ]
      • 例如。 getUrl(int color, {int favNum})
    • 默认
      • 为参数分配默认值。
      • 例如。 getUrl(int color, [int favNum = 6])

?资料来源:stackoverflow.com

问题12:什么是ScopedModel / BLoC模式?

主题:颤振
难度:⭐⭐⭐

ScopedModel和BLoC(业务逻辑组件)是Flutter应用程序的常见架构模式,可帮助将业务逻辑与UI代码分开,并使用更少的状态控件。

  • 范围模型是Flutter框架中未包含的第三方程序包。它是一组实用程序,可让您轻松地将数据模型从父Widget传递到其后代。此外,它还可以在更新模型时重建使用该模型的所有子代。该库最初是从Fuchsia代码库中提取的。

  • BLoC代表业务逻辑组件。它有助于管理状态并从项目的中心位置访问数据。 BLoC的要旨是应将应用程序中的所有内容都表示为事件流:小部件提交事件;其他小部件将响应。 BLoC位于中间,管理对话。

?资料来源:technologymoon.com

Q13:什么是Flutter / Dart中的流?

主题:颤振
难度:⭐⭐⭐

  • Dart中的异步编程的特点是 FutureStream 类。
  • 流是一系列异步事件。这就像一个异步的Iterable,在那里,流告诉您准备就绪时有一个事件,而不是在您请求时获取下一个事件。
  • 流可以通过多种方式创建,但是它们的使用方式都相同。异步for循环(等待)。例如

    Future<int> sumStream(Stream<int> stream) async {
      var sum = 0;
      await for (var value in stream) {
        sum += value;
      }
      return sum;
    }
    
  • 流提供异步的数据序列。

  • 数据序列包括用户生成的事件和从文件读取的数据。

  • 您可以使用“等待”或“ listen() 来自Stream API。

  • 流提供了一种响应错误的方法。

  • 流有两种:单一订阅或广播。

?资料来源:dart.dev

Q14:解释不同类型的流?

主题:颤振
难度:⭐⭐⭐

有两种流。

  1. 单一订阅流

    • 最常见的流。
    • 它包含一系列事件,这些事件是一个较大的整体的一部分。事件必须以正确的顺序传递,并且不能丢失任何事件。
    • 这是您在读取文件或接收Web请求时获得的流。
    • 这样的流只能被收听一次。稍后再次收听可能意味着错过了最初的事件,然后其余部分毫无意义。
    • 当您开始侦听时,数据将被提取并以块的形式提供。
    • 广播流
    • 它用于可一次处理的单个消息。例如,这种流可用于浏览器中的鼠标事件。
    • 您可以随时开始收听这样的流,并且在收听时会触发事件。
    • 多个收听者可以同时收听,您可以在取消上一个订阅后稍后再次收听。

?资料来源:dart.dev

Q15:什么是Flutter中的软件包和插件?

主题:颤振
难度:⭐⭐⭐

  • 包允许您将新的小部件或功能导入到您的应用程序中。
  • 包和插件之间有一个很小的区别。
  • 软件包通常是纯Dart编写的新组件或代码,而插件可以使用本机代码在设备端实现更多功能。
  • 通常在DartPub上,程序包和插件都称为程序包,只有在创建新程序包时才明确提及其区别。

?资料来源:medium.com

Q16:Flutter中的键是什么?何时使用?

主题:颤振
难度:⭐⭐⭐

  • 一种 Key 是一个标识符 WidgetsElementsSemanticsNodes
  • 如果新窗口小部件的键与与该元素关联的当前窗口小部件的键相同,则仅将其用于更新现有元素。
  • 在具有相同父元素的Elements中,键必须唯一。
  • 的子类 Key 应该是子类 LocalKey 要么 GlobalKey
  • 在处理相同类型的小部件集合时,键非常有用。
  • 如果发现自己添加,删除或重新排序具有某种状态的相同类型的小部件集合,则应使用一个键。

?资料来源:api.flutter.dev

Q17:什么是空感知运算符?

主题:颤振
难度:⭐⭐⭐

  • Dart提供了一些方便的运算符来处理可能为null的值。
  • 一个是?? =赋值运算符,它仅在该变量当前为null时才为该变量赋值:

    int a; // The initial value of a is null.
    a ??= 3;
    print(a); // <-- Prints 3.
    
    a ??= 5;
    print(a); // <-- Still prints 3.
    
  • 另一个可识别空值的运算符是??,它会返回左侧的表达式,除非该表达式的值为null,在这种情况下,它会计算并返回其右侧的表达式:

    print(1 ?? 3); // <-- Prints 1.
    print(null ?? 12); // <-- Prints 12.
    

?资料来源:dart.dev

Q18:什么是配置文件模式,何时使用?

主题:颤振
难度:⭐⭐⭐

  • 在配置文件模式下,将保留一些调试功能,足以对应用程序的性能进行配置。
  • 要分析性能时,使用概要文件模式。
  • 在仿真器和模拟器上禁用了概要文件模式,因为它们的行为不能代表实际性能。
  • 在移动设备上,个人资料模式类似于发布模式,但有以下区别:
    • 启用了某些服务扩展,例如启用性能覆盖的扩展。
    • 启用了跟踪,并且支持源代码级调试的工具(例如DevTools)可以连接到该进程。
  • Web应用程序的配置文件模式意味着:
    • 构建没有缩小,但是已经执行了摇树操作。
    • 该应用程序是使用dart2js编译器进行编译的。
  • 命令 flutter run --profile 编译为配置文件模式。

?资料来源:flutter.dev

Q19:什么是发布模式,什么时候使用?

主题:颤振
难度:⭐⭐⭐

  • 当需要最大程度的优化和最小的占用空间时,请使用发布模式来部署应用程序。
  • 准备发布应用程序时,请使用发布模式。
  • 对于移动设备,释放模式(模拟器或模拟器不支持)表示:
    • 断言被禁用。
    • 调试信息被剥离。
    • 调试被禁用。
    • 编译针对快速启动,快速执行和小盘点进行了优化。
      服务扩展已禁用。
  • Web应用程序的发布模式意味着:
    • 最小化了构建,并执行了摇树操作。
    • 该应用程序使用dart2js编译器进行了编译,以实现最佳性能。
  • 命令 flutter run --release 编译为发布模式。
  • 您可以使用以下命令编译为特定目标的发布模式 flutter build

?资料来源:flutter.dev

问题20:如何仅在调试模式下执行代码?

主题:颤振
难度:⭐⭐⭐

解决方法是:

import 'package:flutter/foundation.dart' as Foundation;

那么你可以使用 kReleaseMode 喜欢

if(Foundation.kReleaseMode){ // is Release Mode ??
    print('release mode');
} else {
    print('debug mode');
}

?资料来源:stackoverflow.com

Q21:解释异步,在Flutter / Dart中等待吗?

主题:颤振
难度:⭐⭐⭐⭐

异步操作使您的程序可以在等待另一个操作完成的同时完成工作。以下是一些常见的异步操作:

  • 通过网络获取数据。
  • 写入数据库。
  • 从文件读取数据。

要在Dart中执行异步操作,您可以使用 Future 类和 asyncawait 关键字。

asyncawait 关键字提供了一种声明性的方式来定义异步函数并使用其结果。使用时请记住这两个基本准则 asyncawait

  • 要定义异步功能,请添加 async 在功能主体之前
  • await 关键字仅在 async 功能。

一个 async 功能同步运行,直到第一个 await 关键词。这意味着在 async 函数体,所有同步代码在第一个之前 await 关键字立即执行。

考虑一个例子:

import 'dart:async';

class Employee {
  int id;
  String firstName;
  String lastName;

  Employee(this.id, this.firstName, this.lastName);
}

void main() async {
  print("getting employee...");
  var x = await getEmployee(33);
  print("Got back ${x.firstName} ${x.lastName} with id# ${x.id}");
}

Future<Employee> getEmployee(int id) async {
  //Simluate what a real service call delay may look like by delaying 2 seconds   
  await Future<Employee>.delayed(const Duration(seconds: 2));
  //and then return an employee - lets pretend we grabbed this out of a database 
  var e = new Employee(id, "Joe", "Coder");
  return e;
}

?资料来源:dart.dev

Q22:Flutter / Dart的未来是什么?

主题:颤振
难度:⭐⭐⭐⭐

  • 期货用于表示将来某个时候可用的潜在值或错误。 Future的接收者可以注册一旦值或错误可用的回调。例如:

    Future<int> future = getFuture();
    future.then((value) => handleValue(value))
          .catchError((error) => handleError(error));
    
  • 如果期货无法产生可用价值,那么该期货的类型为 Future

  • 未来表示异步操作的结果,可以有两种状态:

    1. 未完成
      当您调用异步函数时,它将返回未完成的将来。那个未来正在等待函数的异步操作完成或引发错误。

    2. 已完成
      如果异步操作成功,则将来将以一个值完成。否则,它将以错误完成。

?资料来源:api.dart.dev

问题23:Future和Stream有什么异同?

主题:颤振
难度:⭐⭐⭐⭐

相似:

  • FutureStream 两者都是异步工作的。
  • 两者都有一定的潜在价值。

差异:

  • 一种 Stream 是期货的组合。
  • Future 只有一个回应,但 Stream 可以有任意数量的响应。

?资料来源:medium.com

Q24:double.INFINITY和MediaQuery有什么区别?

主题:颤振
难度:⭐⭐⭐⭐

区别可以总结为:

  • 我想和我父母一样大(double.INFINITY
  • 我想和屏幕一样大(MediaQuery)。

通常,您需要使用 double.infinity,但并非总是可能的。一些小部件允许他们的孩子像他们想要的一样大(ColumnListViewOverflowBox…)。在那种情况下使用 double.infinity 产生一个悖论:

  • 父母允许任何大小
  • 孩子想要父母允许的最大尺寸

?资料来源:api.flutter.dev

Q25:Dart AOT如何工作?

主题:颤振
难度:⭐⭐⭐⭐

  • Dart源代码将被翻译为汇编文件,然后汇编器将汇编文件编译为用于不同体系结构的二进制代码。
  • 对于移动应用程序,源代码针对多个处理器ARM,ARM64,x64以及两个平台(Android和iOS)进行编译。这意味着每种支持的处理器和平台组合都有多个结果二进制文件。

?资料来源:flutterbyexample.com

Q26:这些运算符“?”和“?”之间有什么区别?

主题:颤振
难度:⭐⭐⭐⭐

??

  • 这是一个可识别null的运算符,除非该表达式的值为null,否则它将在其左侧返回该表达式,在这种情况下,它将求值并在其右侧返回该表达式:
print(1 ?? 3); // <-- Prints 1.
print(null ?? 12); // <-- Prints 12.

  • 这是一种条件属性访问,用于保护对可能为空的对象的属性或方法的访问,请在点(。)之前添加问号(?):
  • 您可以链接多种用途 ?. 在一个表达式中一起:

    myObject?.someProperty?.someMethod()
    

    前面的代码返回null(并且从不调用 someMethod())(如果有) myObject 要么 myObject.someProperty 一片空白。

?资料来源:flutter.dev

问题27:列出Flutter中的状态管理方法

主题:颤振
难度:⭐⭐⭐⭐⭐

应用程序的状态是应用程序运行时内存中存在的所有内容。其中包括应用程序的资产,Flutter框架保留的有关UI,动画状态,纹理,字体等的所有变量。

  • 颤振框架会自行处理某些状态,例如纹理。
  • 我们管理的状态可以分为两种概念类型:
    • 暂时状态
    • 应用状态

Flutter中状态管理的一些方法是:

  • setState
  • InheritedWidgetInheritedModel
  • 提供者和范围模型
  • Redux
  • BLoC /接收
  • 手机

?资料来源:flutter.dev

Q28:详细说明有状态小部件生命周期

主题:颤振
难度:⭐⭐⭐⭐⭐

有状态小部件具有以下生命周期阶段:

- createState()
- mounted == true
- initState()
- didChangeDependencies()
- build()
- didUpdateWidget()
- setState()
- deactivate()
- dispose()
- mounted == false

createState()

  • 当指示Flutter建立一个 StatefulWidget,它立即调用 createState()。此方法必须存在。一种 StatefulWidget 很少需要比这更复杂。

    class MyHomePage extends StatefulWidget {
      @override
      _MyHomePageState createState() => new _MyHomePageState();
    }
    

安装是真的

  • 什么时候 createState 创建状态类,一个 buildContext 被分配给该状态。
  • 一种 BuildContext 被过分简化的是在此小部件中放置在小部件树中的位置。
  • 所有小部件都有一个布尔值 this.mounted 属性。当 buildContext 被安排了。打电话是错误的 setState 卸载小部件时。

initState()

  • 这是在创建窗口小部件时调用的第一个方法(当然,在类构造函数之后)。
  • initState 只被调用一次。它也必须 super.initState()
  • 此@override方法是执行以下操作的最佳时间:

    • 初始化依赖于特定数据的数据 BuildContext 用于创建的小部件实例。
    • 在树中初始化依赖于此小部件“父级”的属性。
    • 订阅 StreamsChangeNotifiers,或任何其他可能更改此小部件上的数据的对象。

      @override
      initState() {
        super.initState();
        // Add listeners to this class
        cartItemStream.listen((data) {
          _updateWidget(data);
        });
      }
      

didChangeDependencies()

  • didChangeDependencies 方法在之后立即被调用 initState 在第一次构建窗口小部件时。
  • 每当调用此小部件依赖于其数据的对象时,也会调用该方法。例如,如果它依赖于 InheritedWidget,即会更新。
  • build 总是被称为 didChangeDependencies 被称为,因此几乎不需要。但是,此方法是您必须调用的第一个更改 BuildContext.inheritFromWidgetOfExactType。从本质上讲,这将使该状态“侦听”从其继承数据的小部件上的更改。
  • 该文档还建议,如果您需要在 InheritedWidget 更新。

建立()

  • 经常调用此方法(想想fps +渲染)。这是必需的 @override 并且必须返回一个 Widget
  • 请记住,在Flutter中,所有gui都是一个带有一个或多个孩子的小部件,甚至“Padding‘,’Center‘。

didUpdateWidget(Widget oldWidget)

  • didUpdateWidget() 如果父窗口小部件发生更改并且必须重建此窗口小部件(因为需要为其提供不同的数据),则调用该方法,但是使用相同的方法对其进行重建 runtimeType,则调用此方法。
  • 这是因为Flutter正在重用长期存在的状态。在这种情况下,所需的是再次初始化一些数据,就像 initState()
  • 如果国家 build() 方法依赖于 Stream 或其他可以更改的对象,请从旧对象中取消订阅,然后重新订阅 didUpdateWidget()

提示:此方法基本上是“initState()‘如果可以预期 Widget 与小部件的状态关联的状态需要重新构建

  • 颤振总是打电话 build() 在此之后,因此任何后续调用 setState 是多余的。

    @override
    void didUpdateWidget(Widget oldWidget) {
      if (oldWidget.importantProperty != widget.importantProperty) {
        _init();
      }
    }
    

setState()

  • setState()通常从Flutter框架本身和开发人员中调用方法。
  • 它用于通知框架“数据已更改”,并且应重新构建此构建上下文中的小部件。
  • setState() 接受一个不能异步的回调。因此,可以根据需要经常调用它,因为重涂很便宜

    void updateProfile(String name) {
     setState(() => this.name = name);
    }
    

停用()

  • 这很少使用。
  • deactivate()当被称为 State 已从树中删除,但可能会在当前帧更改完成之前将其重新插入。之所以存在这种方法,基本上是因为 State 可以将对象从树中的一个点移动到另一点。

dispose()

  • dispose()State 对象被删除,这是永久的。
  • 可以取消订阅并取消所有动画,流等的方法。

  • 安装错误

  • 状态对象永远无法重新挂载,并且会引发错误 setState() 叫做。

?资料来源:flutterbyexample.com

Q29:调试模式和配置文件模式之间有什么区别?

主题:颤振
难度:⭐⭐⭐⭐⭐

调试模式:

  • 在开发阶段以及您要使用热重装时使用。
  • 默认情况下, flutter run 编译为调试模式。
  • 移动应用程序的调试模式意味着:
    • 断言已启用。
    • 服务扩展已启用。
    • 编译针对快速开发和运行周期进行了优化(但不针对执行速度,二进制大小或部署进行优化)。
    • 启用了调试,并且支持源代码级调试的工具(例如DevTools)可以连接到该进程。
  • Web应用程序的调试模式意味着:
    • 不会缩小版本,也没有执行摇树操作。
    • 该应用程序使用dartdevc编译器进行了编译,以便于调试。

个人资料模式:

  • 要分析性能时,使用概要文件模式。
  • 命令 flutter run --profile 编译为配置文件模式。
  • 在仿真器和模拟器上禁用了概要文件模式,因为它们的行为不能代表实际性能。
  • 在移动设备上,个人资料模式类似于发布模式,但有以下区别:
    • 启用了某些服务扩展,例如启用性能覆盖的扩展。
    • 启用了跟踪,并且支持源代码级调试的工具(例如DevTools)可以连接到该进程。
  • Web应用程序的配置文件模式意味着:
    • 构建没有缩小,但是已经执行了摇树操作。
    • 该应用程序是使用dart2js编译器编译的。

?资料来源:flutter.dev

感谢?阅读并祝您面试顺利
如果愿意,请与您的开发人员分享这篇文章
在?www.fullstack.cafe上查看更多FullStack面试问答。

资讯来源:由0x资讯编译自DEV,原文:https://dev.to/fullstackcafe/29-flutter-interview-questions-mobile-devs-need-to-know-1fon ,版权归作者所有,未经许可,不得转载
你可能还喜欢