怎樣做永久網(wǎng)站二維碼北京seo公司有哪些
Flutter開發(fā)者必備面試問題與答案02
視頻
https://youtu.be/XYSxTb0iA9I
https://www.bilibili.com/video/BV1Zk2dYyEBr/
前言
原文 Flutter 完整面試問題及答案02
本文是 flutter 面試問題的第二講,高頻問答 10 題。
正文
11. PageRoute 是什么?
在 Flutter 中,PageRoute
是一個用于管理應(yīng)用中頁面導(dǎo)航的抽象類。它定義了如何在不同的頁面之間進(jìn)行切換,并提供了一些控制頁面行為的功能。
主要特點(diǎn)
-
頁面切換:
PageRoute
負(fù)責(zé)在不同頁面(或屏幕)之間進(jìn)行導(dǎo)航。它管理了頁面的堆棧,使得用戶可以前往新頁面或返回到之前的頁面。 -
動畫效果:
PageRoute
可以定義頁面切換時的動畫效果。Flutter 提供了一些內(nèi)置的路由實(shí)現(xiàn),比如:-
MaterialPageRoute
:用于 Material Design 風(fēng)格的應(yīng)用,提供從底部向上推入頁面的動畫。 -
CupertinoPageRoute
:用于 iOS 風(fēng)格的應(yīng)用,提供從右向左推入頁面的動畫。
-
-
生命周期管理:
PageRoute
提供了一些生命周期方法,如didChangeDependencies
和dispose
,用于在頁面進(jìn)入和退出時執(zhí)行特定操作。
使用示例
下面是一個使用 MaterialPageRoute
的簡單示例:
import 'package:flutter/material.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget { Widget build(BuildContext context) {return MaterialApp(home: HomePage(),);}
}class HomePage extends StatelessWidget { Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Home Page')),body: Center(child: ElevatedButton(child: Text('Go to Second Page'),onPressed: () {Navigator.push(context,MaterialPageRoute(builder: (context) => SecondPage()),);},),),);}
}class SecondPage extends StatelessWidget { Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Second Page')),body: Center(child: Text('Welcome to the Second Page!'),),);}
}
自定義 PageRoute
你可以創(chuàng)建自定義的 PageRoute
來實(shí)現(xiàn)特定的導(dǎo)航效果。例如,以下是一個簡單的自定義路由實(shí)現(xiàn):
class CustomPageRoute extends PageRouteBuilder {final Widget page;CustomPageRoute({required this.page}): super(pageBuilder: (context, animation, secondaryAnimation) => page,transitionsBuilder: (context, animation, secondaryAnimation, child) {const begin = Offset(1.0, 0.0);const end = Offset.zero;const curve = Curves.easeInOut;var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));var offsetAnimation = animation.drive(tween);return SlideTransition(position: offsetAnimation,child: child,);},);
}
12. 解釋 async , await 和 Future ?
在 Flutter 和 Dart 中,async
、await
和 Future
是處理異步編程的關(guān)鍵概念。它們可以幫助你編寫非阻塞的代碼,使得應(yīng)用能夠在執(zhí)行長時間運(yùn)行的任務(wù)時保持響應(yīng)。以下是對這三個概念的詳細(xì)解釋:
1. Future
-
定義:
Future
是一個表示可能在未來某個時間點(diǎn)完成的異步操作的對象。它可以用于表示一個延遲的值,通常用于處理異步任務(wù)的結(jié)果。 -
狀態(tài):
- 未完成(Pending):
Future
仍在進(jìn)行中。 - 已完成(Completed):
Future
執(zhí)行完畢,可以獲取結(jié)果。 - 已失敗(Error):
Future
執(zhí)行過程中出現(xiàn)錯誤。
- 未完成(Pending):
-
使用示例:
Future<String> fetchData() async {// 模擬網(wǎng)絡(luò)請求await Future.delayed(Duration(seconds: 2));return 'Data fetched'; }
2. async
-
定義:
async
是一個修飾符,用于聲明一個異步函數(shù)。使用async
修飾的函數(shù)會返回一個Future
,即使函數(shù)內(nèi)部沒有顯式地返回Future
。 -
特點(diǎn):
- 在
async
函數(shù)中,你可以使用await
關(guān)鍵字等待一個Future
完成。 async
函數(shù)會自動將返回值包裝在一個Future
中。
- 在
-
使用示例:
Future<void> loadData() async {String data = await fetchData();print(data); // 輸出 'Data fetched' }
3. await
-
定義:
await
是一個關(guān)鍵字,用于在async
函數(shù)中等待一個Future
完成,并返回其結(jié)果。 -
特點(diǎn):
await
只能在async
函數(shù)中使用。- 使用
await
會暫停async
函數(shù)的執(zhí)行,直到Future
完成,并返回結(jié)果。 await
讓異步代碼看起來像同步代碼,從而提高代碼的可讀性。
-
使用示例:
Future<void> main() async {print('Fetching data...');await loadData(); // 等待 loadData 完成print('Data loaded'); }
整體示例
下面是一個完整的示例,展示了如何使用 async
、await
和 Future
:
import 'dart:async';Future<String> fetchData() async {// 模擬網(wǎng)絡(luò)請求await Future.delayed(Duration(seconds: 2));return 'Data fetched';
}Future<void> loadData() async {String data = await fetchData();print(data);
}Future<void> main() async {print('Fetching data...');await loadData(); // 等待 loadData 完成print('Data loaded');
}
- Future:表示一個異步操作的結(jié)果,可以是未完成、已完成或已失敗。
- async:用于聲明異步函數(shù),返回一個
Future
。 - await:在
async
函數(shù)中等待一個Future
完成,并獲取其結(jié)果。
通過使用 async
、await
和 Future
,你可以輕松地處理異步操作,使代碼更加簡潔和可讀。
13. 你如何動態(tài)更新列表視圖?
在 Flutter 中,動態(tài)更新列表視圖通常使用 ListView
組件結(jié)合狀態(tài)管理來實(shí)現(xiàn)。以下是幾種常見的方法來動態(tài)更新列表視圖:
1. 使用 StatefulWidget
利用 StatefulWidget
和 setState()
方法,可以在更新數(shù)據(jù)時重新構(gòu)建列表。
示例:
import 'package:flutter/material.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget { Widget build(BuildContext context) {return MaterialApp(home: DynamicList(),);}
}class DynamicList extends StatefulWidget { _DynamicListState createState() => _DynamicListState();
}class _DynamicListState extends State<DynamicList> {List<String> items = ['Item 1', 'Item 2', 'Item 3'];void _addItem() {setState(() {items.add('Item ${items.length + 1}');});} Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Dynamic List')),body: ListView.builder(itemCount: items.length,itemBuilder: (context, index) {return ListTile(title: Text(items[index]),);},),floatingActionButton: FloatingActionButton(onPressed: _addItem,child: Icon(Icons.add),),);}
}
2. 使用 Provider
或其他狀態(tài)管理
如果你的應(yīng)用較復(fù)雜,使用狀態(tài)管理庫(如 Provider
、Bloc
、Riverpod
等)可以更好地管理狀態(tài)和更新列表視圖。
示例(使用 Provider):
首先,添加 provider
依賴到 pubspec.yaml
:
dependencies:provider: ^6.0.0
然后,創(chuàng)建一個 ChangeNotifier
類來管理狀態(tài):
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';void main() {runApp(ChangeNotifierProvider(create: (context) => ItemList(),child: MyApp(),),);
}class MyApp extends StatelessWidget { Widget build(BuildContext context) {return MaterialApp(home: DynamicList(),);}
}class ItemList extends ChangeNotifier {List<String> items = ['Item 1', 'Item 2', 'Item 3'];void addItem() {items.add('Item ${items.length + 1}');notifyListeners();}
}class DynamicList extends StatelessWidget { Widget build(BuildContext context) {final itemList = Provider.of<ItemList>(context);return Scaffold(appBar: AppBar(title: Text('Dynamic List')),body: ListView.builder(itemCount: itemList.items.length,itemBuilder: (context, index) {return ListTile(title: Text(itemList.items[index]),);},),floatingActionButton: FloatingActionButton(onPressed: () {itemList.addItem();},child: Icon(Icons.add),),);}
}
3. 使用 StreamBuilder
如果數(shù)據(jù)來自異步源(如網(wǎng)絡(luò)請求或數(shù)據(jù)庫),可以使用 StreamBuilder
來動態(tài)更新列表。
示例:
import 'dart:async';
import 'package:flutter/material.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget { Widget build(BuildContext context) {return MaterialApp(home: StreamList(),);}
}class StreamList extends StatelessWidget {final StreamController<String> _controller = StreamController<String>();void _addItem() {_controller.sink.add('Item ${DateTime.now()}');} Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Stream List')),body: StreamBuilder<String>(stream: _controller.stream,builder: (context, snapshot) {if (snapshot.hasData) {return ListTile(title: Text(snapshot.data!));}return Center(child: Text('No items'));},),floatingActionButton: FloatingActionButton(onPressed: _addItem,child: Icon(Icons.add),),);}void dispose() {_controller.close();super.dispose();}
}
14. stream 是什么?
在 Flutter 和 Dart 中,Stream 是一種用于處理異步數(shù)據(jù)流的機(jī)制。它允許你接收一系列異步事件,而不僅僅是單個值。Streams 非常適合處理動態(tài)數(shù)據(jù)源,例如用戶輸入、網(wǎng)絡(luò)請求、文件讀取等。
主要特點(diǎn)
-
異步數(shù)據(jù)處理:
- Stream 允許你以異步的方式接收數(shù)據(jù),不會阻塞當(dāng)前線程。這使得應(yīng)用在處理數(shù)據(jù)時仍然能夠保持響應(yīng)。
-
多個值:
- 與
Future
只返回一個單一值不同,Stream 可以發(fā)送多個值,可以是事件、消息或數(shù)據(jù)。
- 與
-
監(jiān)聽:
- 你可以通過添加監(jiān)聽器(Listener)來接收來自 Stream 的數(shù)據(jù)。每當(dāng) Stream 中有新數(shù)據(jù)可用時,監(jiān)聽器會被調(diào)用。
Stream 的類型
-
單訂閱 Stream:
- 只能有一個訂閱者,適合處理一次性事件流,例如從文件讀取數(shù)據(jù)。
-
廣播 Stream:
- 可以有多個訂閱者,適合處理需要廣播給多個監(jiān)聽者的事件,例如用戶輸入或網(wǎng)絡(luò)請求。
基本使用示例
以下是一個簡單的 Stream 使用示例,展示了如何創(chuàng)建和監(jiān)聽 Stream:
import 'dart:async';void main() {// 創(chuàng)建一個單訂閱 StreamStream<int> numberStream = Stream<int>.periodic(Duration(seconds: 1), (count) => count);// 監(jiān)聽 StreamnumberStream.listen((number) {print('Received number: $number');});
}
停止監(jiān)聽
你可以通過調(diào)用 cancel()
方法來停止監(jiān)聽 Stream:
import 'dart:async';void main() {Stream<int> numberStream = Stream<int>.periodic(Duration(seconds: 1), (count) => count);var subscription = numberStream.listen((number) {print('Received number: $number');if (number >= 5) {subscription.cancel(); // 停止監(jiān)聽}});
}
使用 StreamBuilder
在 Flutter 中,通常使用 StreamBuilder
來構(gòu)建 UI,自動響應(yīng) Stream 的數(shù)據(jù)變化。下面是一個使用 StreamBuilder
的示例:
import 'dart:async';
import 'package:flutter/material.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget { Widget build(BuildContext context) {return MaterialApp(home: StreamExample(),);}
}class StreamExample extends StatelessWidget {final Stream<int> numberStream = Stream<int>.periodic(Duration(seconds: 1), (count) => count); Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Stream Example')),body: Center(child: StreamBuilder<int>(stream: numberStream,builder: (context, snapshot) {if (snapshot.connectionState == ConnectionState.waiting) {return CircularProgressIndicator();} else if (snapshot.hasError) {return Text('Error: ${snapshot.error}');} else {return Text('Received number: ${snapshot.data}');}},),),);}
}
15. keys 在 Flutter 中是什么,你什么時候應(yīng)該使用它?
在 Flutter 中,Keys 是一個用于標(biāo)識 Widget 的對象,幫助 Flutter 識別和管理 Widget 的狀態(tài)。Keys 在構(gòu)建和更新 Widget 時起到重要作用,尤其是在涉及到狀態(tài)管理、列表和動畫時。
Keys 的類型
-
GlobalKey:
-
用于跨 Widget 樹訪問狀態(tài)??梢栽诓煌牡胤揭猛粋€ Widget 的狀態(tài)。
-
示例:在頁面間導(dǎo)航時,保持表單狀態(tài)。
-
-
ValueKey:
-
根據(jù)給定的值來識別 Widget,通常用于列表中的元素。
-
示例:在列表中修改順序時,確保正確更新每個元素的狀態(tài)。
-
-
ObjectKey:
- 通過對象的引用來識別 Widget,適用于需要比較對象的情況。
-
UniqueKey:
- 每次創(chuàng)建時都會生成一個唯一的 Key,適合臨時 Widget。
使用場景
列表的動態(tài)更新:
- 當(dāng)你在列表中添加、刪除或重新排序項(xiàng)時,使用 Keys 可以幫助 Flutter 確定哪些 Widget 需要更新,從而避免不必要的重建。
ListView.builder(itemCount: items.length,itemBuilder: (context, index) {return ListTile(key: ValueKey(items[index]), // 使用 ValueKeytitle: Text(items[index]),);},
);
保持狀態(tài):
- 使用
GlobalKey
時,可以在 Widget 重建時保留其狀態(tài)。例如,在使用Form
組件時,可以通過GlobalKey
訪問表單狀態(tài)。
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();Form(key: _formKey,child: TextFormField(// ...),
);
動畫和過渡:
- 在使用動畫時,Keys 可以幫助 Flutter 確定哪個 Widget 應(yīng)該保持其狀態(tài)或動畫效果,從而實(shí)現(xiàn)更流暢的過渡。
構(gòu)建條件 Widget:
- 當(dāng)根據(jù)某些條件創(chuàng)建 Widget 時,使用 Keys 可以確保 Flutter 正確管理這些 Widget 的狀態(tài)。
16. GlobalKeys 是什么?
在 Flutter 中,GlobalKey
是一種特殊的 Key,用于跨 Widget 樹訪問狀態(tài)和方法。GlobalKey
允許你在不同的 Widget 之間共享狀態(tài),特別是在使用 StatefulWidget
時。它的主要用途是確保在 Widget 樹重建時仍能保留和訪問 Widget 的狀態(tài)。
GlobalKey
的特點(diǎn)
-
跨 Widget 樹訪問:
GlobalKey
允許你從不同的地方訪問同一個 Widget 的狀態(tài)。使用GlobalKey
,你可以在 Widget 的外部調(diào)用其狀態(tài)方法,比如在表單中驗(yàn)證字段。
-
唯一性:
- 每個
GlobalKey
都是唯一的,因此 Flutter 能夠確保在 Widget 樹中識別每個 Widget。
- 每個
-
持久性:
- 當(dāng) Widget 被重建時,
GlobalKey
保持對其狀態(tài)的引用,因此可以在重建過程中保持狀態(tài)。
- 當(dāng) Widget 被重建時,
使用場景
- 表單狀態(tài)管理:
- 在處理表單時,你可以使用
GlobalKey
來訪問和驗(yàn)證表單的狀態(tài)。
- 在處理表單時,你可以使用
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
Widget build(BuildContext context) {return Form(key: _formKey,child: Column(children: [TextFormField(validator: (value) {if (value == null || value.isEmpty) {return 'Please enter some text';}return null;},),ElevatedButton(onPressed: () {if (_formKey.currentState?.validate() ?? false) {// 處理表單提交}},child: Text('Submit'),),],),);
}
-
控制 Widget 的狀態(tài):
- 使用
GlobalKey
可以直接控制 Widget 的狀態(tài)方法,比如在動畫中調(diào)用。
- 使用
-
在復(fù)雜布局中保持狀態(tài):
- 當(dāng)你的 Widget 樹結(jié)構(gòu)復(fù)雜,且多個子 Widget 可能會被重建時,
GlobalKey
可以幫助你保持子 Widget 的狀態(tài)。
- 當(dāng)你的 Widget 樹結(jié)構(gòu)復(fù)雜,且多個子 Widget 可能會被重建時,
17. 何時應(yīng)使用 mainAxisAlignment 和 crossAxisAlignment?
18. 你什么時候可以使用 double.INFINITY ?
當(dāng)你希望該小部件的大小與父小部件相同,請?jiān)试S
19. Ticker 、 Tween 和 AnimationController 是什么?
在 Flutter 中,Ticker
、Tween
和 AnimationController
是用于實(shí)現(xiàn)動畫的關(guān)鍵組件。它們各自有不同的角色和功能,下面是對它們的詳細(xì)解釋:
1. Ticker
-
定義:
Ticker
是一個用于生成時間片的對象,它會在每一幀(frame)中調(diào)用一個回調(diào)函數(shù)。它通常與動畫相關(guān)聯(lián),并用于控制動畫的更新頻率。 -
工作原理:
Ticker
會在每一幀調(diào)用回調(diào),并提供當(dāng)前的時間戳。你可以使用這個時間戳來更新動畫的狀態(tài)。
-
使用場景:
- 通常在自定義動畫或使用
AnimationController
時,Ticker
是由AnimationController
自動創(chuàng)建和管理的。
- 通常在自定義動畫或使用
2. Tween
-
定義:
Tween
是一個用于定義動畫起始值和結(jié)束值的對象。它幫助你在動畫的不同狀態(tài)之間插值(interpolate)。 -
工作原理:
Tween
接受兩個值,分別是起始值和結(jié)束值,然后在這兩個值之間生成中間值。你可以使用Tween
來處理各種類型的值,例如顏色、尺寸、位置等。
-
使用示例:
Tween<double> tween = Tween<double>(begin: 0.0, end: 1.0); double value = tween.transform(0.5); // value = 0.5
3. AnimationController
-
定義:
AnimationController
是一個特殊的Animation
,它可以控制動畫的播放。它負(fù)責(zé)管理動畫的生命周期,包括啟動、停止、反轉(zhuǎn)等。 -
工作原理:
AnimationController
需要一個vsync
參數(shù),這通常是SingleTickerProviderStateMixin
或TickerProviderStateMixin
的實(shí)例。它生成一個從 0.0 到 1.0 的值,表示動畫的進(jìn)度。
-
使用場景:
- 在需要控制動畫的開始、停止和反轉(zhuǎn)時使用
AnimationController
。
- 在需要控制動畫的開始、停止和反轉(zhuǎn)時使用
示例:結(jié)合使用 Ticker、Tween 和 AnimationController
以下是一個簡單的示例,展示如何使用 Ticker
、Tween
和 AnimationController
創(chuàng)建一個動畫:
import 'package:flutter/material.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget { Widget build(BuildContext context) {return MaterialApp(home: AnimatedBox());}
}class AnimatedBox extends StatefulWidget { _AnimatedBoxState createState() => _AnimatedBoxState();
}class _AnimatedBoxState extends State<AnimatedBox> with SingleTickerProviderStateMixin {late AnimationController _controller;late Animation<double> _animation;void initState() {super.initState();_controller = AnimationController(duration: const Duration(seconds: 2),vsync: this,);_animation = Tween<double>(begin: 0.0, end: 300.0).animate(_controller);_controller.forward(); // 啟動動畫}void dispose() {_controller.dispose(); // 釋放資源super.dispose();} Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Animation Example')),body: Center(child: AnimatedBuilder(animation: _animation,builder: (context, child) {return Container(width: _animation.value,height: _animation.value,color: Colors.blue,);},),),);}
}
- Ticker:用于生成時間片,通常與動畫相關(guān)聯(lián)。
- Tween:定義動畫的起始值和結(jié)束值,用于在值之間插值。
- AnimationController:控制動畫的播放,包括啟動、停止和反轉(zhuǎn)。它生成一個時間值(通常在 0.0 到 1.0 之間),用于與
Tween
結(jié)合使用。
20. ephemeral 狀態(tài)是什么?
在 Flutter 中,ephemeral 狀態(tài)(短暫狀態(tài))指的是一種狀態(tài),它是局部的、短期的,并且只在當(dāng)前 Widget 的生命周期內(nèi)有效。這種狀態(tài)通常不需要持久化,也不需要在 Widget 樹之外共享。
特點(diǎn)
-
局部性:
- Ephemeral 狀態(tài)通常只與一個特定的 Widget 相關(guān)聯(lián)。它不會影響其他 Widget。
-
短暫性:
- 該狀態(tài)在 Widget 被創(chuàng)建時存在,在 Widget 被銷毀時消失。它不需要跨多個 Widget 或屏幕保持。
-
使用
StatefulWidget
:- Ephemeral 狀態(tài)通常通過
StatefulWidget
來管理。StatefulWidget
的State
對象可以包含所有的局部狀態(tài)。
- Ephemeral 狀態(tài)通常通過
使用場景
- 用戶輸入:例如,文本框的內(nèi)容、復(fù)選框的選中狀態(tài)等。
- 動畫狀態(tài):例如,動畫的當(dāng)前進(jìn)度或狀態(tài)。
- UI 狀態(tài):例如,按鈕的啟用和禁用狀態(tài)、加載指示器的可見性等。
示例
下面是一個簡單的例子,演示如何在 StatefulWidget
中管理 ephemeral 狀態(tài):
import 'package:flutter/material.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget { Widget build(BuildContext context) {return MaterialApp(home: Counter());}
}class Counter extends StatefulWidget { _CounterState createState() => _CounterState();
}class _CounterState extends State<Counter> {int _count = 0; // 這是一個 ephemeral 狀態(tài)void _incrementCounter() {setState(() {_count++; // 更新局部狀態(tài)});} Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Ephemeral State Example')),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Text('You have pushed the button this many times:'),Text('$_count',style: Theme.of(context).textTheme.headline4,),],),),floatingActionButton: FloatingActionButton(onPressed: _incrementCounter,tooltip: 'Increment',child: Icon(Icons.add),),);}
}
Ephemeral 狀態(tài)是 Flutter 中一種局部且短期存在的狀態(tài),適合用于管理特定 Widget 的狀態(tài)。它通過 StatefulWidget
管理,適用于用戶輸入、動畫和 UI 狀態(tài)等場景。與之相對的是 app 狀態(tài)(應(yīng)用狀態(tài)),后者是需要在多個 Widget 之間共享的持久狀態(tài)。
小結(jié)
感謝閱讀本文
如果有什么建議,請?jiān)谠u論中讓我知道。我很樂意改進(jìn)。
貓哥 APP
- SaaS Fast
- Flutter GetX Generator
flutter 學(xué)習(xí)路徑
- Flutter 優(yōu)秀插件推薦
- Flutter 基礎(chǔ)篇1 - Dart 語言學(xué)習(xí)
- Flutter 基礎(chǔ)篇2 - 快速上手
- Flutter 實(shí)戰(zhàn)1 - Getx Woo 電商APP
- Flutter 實(shí)戰(zhàn)2 - 上架指南 Apple Store、Google Play
- Flutter 基礎(chǔ)篇3 - 仿微信朋友圈
- Flutter 實(shí)戰(zhàn)3 - 騰訊即時通訊 第一篇
- Flutter 實(shí)戰(zhàn)4 - 騰訊即時通訊 第二篇
? 貓哥
ducafecat.com
end