在理解這些問題之前,建議看一下Flutter架構原理,如下鏈接:
https://blog.csdn.net/wang_yong_hui_1234/article/details/130427887?spm=1001.2014.3001.5501
一. 有個Text節(jié)點,由于文字內(nèi)容過多,發(fā)生了溢出錯誤,該如何解決?
1.使用overflow屬性
Text(
'這是一個很長的文本內(nèi)容,可能會導致溢出錯誤。',
overflow: TextOverflow.ellipsis, // 或者 TextOverflow.fade
)
2.使用maxLines屬性
Text(
'這是一個很長的文本內(nèi)容,可能會導致溢出錯誤。',
maxLines: 2,
)
3.使用Expanded或Flexible
Row(
children: [
Expanded(
child: Text(
'這是一個很長的文本內(nèi)容,可能會導致溢出錯誤。',
overflow: TextOverflow.ellipsis,
),
),
],
)
4.使用ListView或SingleChildScrollView
SingleChildScrollView(
child: Text(
'這是一個很長的文本內(nèi)容,可能會導致溢出錯誤。',
),
)
二.Widget、Element、RenderObject三者之間的關系?
- Widget是UI的聲明式描述,它們通常是層次結構的頂部。
- Element是Widget的實例,它們構成了渲染樹,并管理了Widget的生命周期和狀態(tài)。
- RenderObject是渲染樹的實際工作單位,負責執(zhí)行實際的繪制和布局。
三.什么是有狀態(tài)(Stateful)和無狀態(tài)(Stateless)Widget?它們之間有什么區(qū)別?
-
有狀態(tài)(Stateful)Widget:
- 有狀態(tài)Widget是一種可以包含可變狀態(tài)的Widget類型。
- 當其內(nèi)部狀態(tài)(state)發(fā)生變化時,可以通知Flutter框架進行重新構建,并且可以在多次構建之間保留狀態(tài)。
- 通常在需要響應用戶交互或數(shù)據(jù)更新時使用,比如表單、按鈕、動畫等。
- 有狀態(tài)Widget通常包括兩個類:一個是繼承自
StatefulWidget
的Widget類,另一個是繼承自State
的狀態(tài)類,狀態(tài)類包含了Widget的可變狀態(tài)。
示例:
class MyStatefulWidget extends StatefulWidget { _MyStatefulWidgetState createState() => _MyStatefulWidgetState(); } class _MyStatefulWidgetState extends State<MyStatefulWidget> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } Widget build(BuildContext context) { return Column( children: <Widget>[ Text('Counter: $_counter'), ElevatedButton( onPressed: _incrementCounter, child: Text('Increment'), ), ], ); } }
-
無狀態(tài)(Stateless)Widget:
- 無狀態(tài)Widget是一種不包含可變狀態(tài)的Widget類型。
- 它們通常用于展示靜態(tài)內(nèi)容或不需要重新構建的部分,因為它們在構建后不會發(fā)生變化。
- 無狀態(tài)Widget是不可變的,一旦構建就不能再修改內(nèi)部狀態(tài)。
- 通常用于構建UI的靜態(tài)部分,以提高性能。
示例:
class MyStatelessWidget extends StatelessWidget { Widget build(BuildContext context) { return Text('Hello, World!'); } }
總的來說,有狀態(tài)Widget適用于需要管理可變狀態(tài)的場景,而無狀態(tài)Widget適用于靜態(tài)內(nèi)容的展示。使用它們的組合可以有效地構建復雜的用戶界面,同時保持性能和可維護性。
四.Flutter中的路由是什么?如何導航到新的頁面?
路由是用于導航和管理不同頁面(或稱為屏幕)之間切換的機制。Flutter的路由系統(tǒng)允許您在應用程序中創(chuàng)建多個頁面,并實現(xiàn)頁面之間的導航。
Flutter中有兩種常見的路由:命名路由和普通(非命名)路由
MaterialApp(
routes: {
'/': (context) => HomeScreen(),
'/second': (context) => SecondScreen(),
},
// ...
)
// 導航到命名路由
Navigator.pushNamed(context, '/second');
// 導航到新頁面
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
第三方路由框架:
go_router:https://pub.dev/packages?q=go_router
auto_route:https://pub.dev/packages/auto_route
五.什么是Flutter的狀態(tài)管理?有哪些狀態(tài)管理庫可用?
Flutter應用程序通常會包含許多不同的小部件,這些小部件可能需要訪問和共享數(shù)據(jù),而狀態(tài)管理的目標是使這個過程更加有組織和高效。
狀態(tài)管理:
- InheritedWidget:InheritedWidget是Flutter框架提供的一種狀態(tài)共享機制。它允許您在小部件樹中共享數(shù)據(jù),以便子小部件可以輕松訪問共享狀態(tài)。這在跨多個小部件傳遞數(shù)據(jù)時非常有用。
- Provider:Provider是一個開源的Flutter狀態(tài)管理庫,它建立在InheritedWidget之上,并提供了更簡化的數(shù)據(jù)共享和更新方式。它通常與Consumer小部件一起使用,以便小部件只在相關數(shù)據(jù)發(fā)生變化時重新構建。
- flutter_bloc :它提供了用于實現(xiàn)BLoC設計模式的工具和類,提供了一種清晰、可測試和可維護的方式來管理Flutter應用程序的狀態(tài)和業(yè)務邏輯。它將狀態(tài)與UI分離,使得應用程序更易于擴展和修改
六.請解釋Flutter的Widget生命周期
initState
當插入渲染樹的時候調(diào)用,這個函數(shù)在生命周期中只調(diào)用一次。這里可以做一些初始化工作,比如初始化State的變量。
didChangeDependencies
在Widget構建后,如果依賴的InheritedWidget發(fā)生變化,則會調(diào)用此方法。通常用于處理數(shù)據(jù)依賴關系的變化
didUpdateWidget
當組件的狀態(tài)改變的時候就會調(diào)用didUpdateWidget,比如調(diào)用了setState。
deactivate
這通常用于在Widget不再可見或處于非活動狀態(tài)時執(zhí)行一些清理工作。
dispose
在Widget從Widget樹中移除后,會調(diào)用dispose方法,用于釋放資源和取消訂閱。
七.什么是Flutter的Key?它們的作用是什么?
Key是一個重要的概念,用于標識Widget并確保它們在Widget樹中的唯一性。用于標識和查找Widget。
常用的key:
- ValueKey: 通過一個特定的值作為標識。
- ObjectKey: 通過一個對象作為標識。
- GlobalKey: 全局標識,通常用于跨Widget樹中的狀態(tài)共享。
ValueKey使用:
Widget build(BuildContext context) {
return ListView(
children: <Widget>[
ListTile(
key: ValueKey('item_1'),
title: Text('Item 1'),
),
ListTile(
key: ValueKey('item_2'),
title: Text('Item 2'),
),
// ...
],
);
}
在這個示例中,我們?yōu)槊總€ListTile指定了一個不同的ValueKey,以確保它們在列表中的位置可以被正確標識。
ObjectKey使用
final myObject = MyCustomObject(); // 創(chuàng)建一個自定義對象
Widget build(BuildContext context) {
return ListView(
children: <Widget>[
ListTile(
key: ObjectKey(myObject), // 使用ObjectKey關聯(lián)自定義對象
title: Text('Item 1'),
),
ListTile(
key: ObjectKey('some_string'), // 使用ObjectKey關聯(lián)字符串
title: Text('Item 2'),
),
// ...
],
);
}
在這個示例中,我們創(chuàng)建了一個自定義對象myObject,并使用ObjectKey將其關聯(lián)到ListTile上。這意味著當myObject發(fā)生變化時,與其關聯(lián)的ListTile將被認為需要更新。
八.Dart是單線程模型,如何運行的?
Dart 在單線程中是以消息循環(huán)機制來運行的,其中包含兩個任務隊列,一個是“微任務隊列” microtask queue,另一個叫做“事件隊列” event queue。
九.var、final、const、late介紹
- var: 定義的變量會自動推斷類型,如果沒有初始化,那么它的值是nil。在聲明時賦值,相當于確定了類型。
- final: 可以先聲明再次賦值,但是只能賦值一次
- const: 修飾常量,聲明的時候就得賦值
- late: 延遲初始化變量,如果這個變量沒有被使用的話就不會被初始化。
十.Future,Steam,async,await 區(qū)別和原理?
Future
Future 表示一個可能會在未來完成的操作,通常用于執(zhí)行一些需要時間的任務,如網(wǎng)絡請求、文件讀寫、計算等。
Future 具有以下幾種狀態(tài):
- 未完成:Future 正在執(zhí)行或等待執(zhí)行;
- 完成:Future 成功完成并返回一個值;
- 失?。篎uture 執(zhí)行時發(fā)生了錯誤;
try/catch未能夠捕獲future中的異常,因此future中的異常只能通過catchError()或在then()方法中傳入可選參數(shù)onError來進行捕獲和處理。
相關方法
- Future.wait():等待多個Future全部完成后才返回結果
async/await
如果說Future是一個盒子,當你使用Future直接返回給你個盒子,并且不會阻塞。而async/await就是為了打開這個盒子,拿到執(zhí)行的結果。
async 和 await 的核心原理是,它們通過暫停和恢復異步函數(shù)的執(zhí)行,使得程序能夠繼續(xù)處理其他任務,而不會被異步操作所阻塞。
十一.空檢查問題
1.name??‘默認’
這段代碼的含義:當name為空時給個默認值。
2. name!
如果name為空,這段代碼會出現(xiàn)什么情況:在debug模式下會顯示紅色,在release模式下顯示一塊灰色
3.name?.length
如果 name 為 null,則 length 為 null;否則為 name.length 的值
十二.InheritedWidget如何實現(xiàn)共享的
其實在 Element 的內(nèi)部有一個 Map<Type, InheritedElement> _inheritedWidgets; 參數(shù),
_inheritedWidgets 一般情況下是空的,只有當父控件是 InheritedWidget 或者本身是 InheritedWidget 時,它才會被初始化,而當父控件是 InheritedWidget 時,這個 Map 會被一級一級往下傳遞與合并。
十三.Flutter如何支持原生View的
Flutter 支持兩種集成模式:虛擬顯示模式 (Virtual displays) 和混合集成模式 (Hybrid composition)
虛擬顯示模式 (Virtual displays)
這種方式使用比較簡單:
AndroidView(
viewType: viewType,
layoutDirection: TextDirection.ltr,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
)
以 Android 為例,Android 上是利用了副屏顯示的底層邏輯,使用 VirtualDisplay 類,創(chuàng)建一個虛擬顯示器,需要調(diào)用 DisplayManager 的 createVirtualDisplay() 方法,將虛擬顯示器的內(nèi)容渲染在一個內(nèi)存的 Surface 上 ,生成一個唯一的 textureId 。
如下圖,之后渲染時將 textureId 傳遞給 Dart 層,渲染引擎會根據(jù) textureId , 獲取到內(nèi)存里已渲染數(shù)據(jù),繪制到 AndroidView 上進行顯示。
混合集成模式 (Hybrid composition)
會將原生的 android.view.View 附加到視圖層次結構中。因此,鍵盤處理和無障礙功能是開箱即用的。在 Android 10 之前,此模式可能會大大降低 Flutter UI 的幀吞吐量 (FPS)文章來源:http://www.zghlxwxcb.cn/news/detail-719988.html
相對會比直接使用 AndroidView 在代碼上更復雜一點, 需要使用到 PlatformViewLink、 AndroidViewSurface 和 PlatformViewsService 這三個對象文章來源地址http://www.zghlxwxcb.cn/news/detail-719988.html
Widget build(BuildContext context) {
// This is used in the platform side to register the view.
const String viewType = '<platform-view-type>';
// Pass parameters to the platform side.
const Map<String, dynamic> creationParams = <String, dynamic>{};
return PlatformViewLink(
viewType: viewType,
surfaceFactory: (context, controller) {
return AndroidViewSurface(
controller: controller as AndroidViewController,
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
);
},
onCreatePlatformView: (params) {
return PlatformViewsService.initSurfaceAndroidView(
id: params.id,
viewType: viewType,
layoutDirection: TextDirection.ltr,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
onFocus: () {
params.onFocusChanged(true);
},
)
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
..create();
},
);
}
到了這里,關于Flutter最全面試題大全的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!