flutter 的一些概念三

woodWu發表於2024-09-06

本文同步釋出於公眾號:stringwu的網際網路雜談:flutter 的一些概念三

1 Stream 與 Future的關係

StreamFuture 都是 Flutter 中常用的非同步程式設計模型,Future 適用於一次性非同步操作,Stream 適用於連續的非同步操作

1.1 Future

  • Future一次性的操作,只會返回一個結果;
  • 可以使用awaitasync 等關鍵字來等待結果
  • 可透過Future.then 方法來處理非同步操作的結果
  • Future.timeout 來設定超進的時間

1.2 Stream

  • Stream是連續的非同步操作,它可以多次返回結果;
  • 需要使用StreamController 和 StreamBuilder 來監聽資料流動,並對資料進行處理;
  • 可以使用Stream.listen 方法來監聽資料的流動,並進行一個處理
  • Stream.timeout 來設定超時的時間
  • 使用StreamControllerStreamSubscription 來實現資料的訂閱和消費
    一個簡單的實現資料訂閱和消費邏輯
StreamController<int> _controller = StreamController<int>();
_controller.add(1);
_controller.add(2);
_controller.add(3);

// 訂閱和消費
StreamSubscription<int> _subscription = _controller.stream.listen((int value) {
  print(value);
});

2 Widget、State、Context的區別與聯絡

  • WidgetFlutter 中構建 UI 的基本單位,它描述了一個 UI 元素的外觀和行為。Widget 可以是有狀態的(StatefulWidget)或無狀態的(Stateless Widget),可以包含其他 Widget,可以組成 Widget 樹。

  • StateWidget 的狀態,它描述了 Widget 在特定時間點的資料和行為。State 只能存在於有狀態的 Widget 中,它可以隨著時間的推移而改變,但不會影響 Widget 樹的結構

  • ContextFlutter 中的上下文物件,它包含了當前 WidgetWidget 樹中的位置和狀態資訊。Context 可以用來獲取當前 ThemeMediaQueryNavigator 等資訊,也可以用來建立新的 Widget。

3 PlatformView

PlatformView 可以將原生的檢視嵌入到Flutter UI中,如嵌入原生地圖,影片播放等。在使用中,需要透過PlatformView WidgetPlatformViewFactory 來實現:

  • PlatformView Widget 用於將原生影片嵌入到應用中;
  • PlatformViewFactory 主要用來建立PlatformView Widget 並將原生檢視與PlatformView Widget 進行關聯;

3.1簡單的使用示例(以Android為例)

首先在原生程式碼中建立一個自定義的PlatformView

// 步驟1 建立一個自定義的PlatformView
class DemoAView :PlatformView {
// 裡面的內容就和在原生中實現自定義View一樣
.....
}

// 步驟2 再建立一個Factory來建立PlatformView
class DemoAViewFactory : PlaformViewFactory {
 override fun create(context: Context, id: Int, args: Any?): PlatformView {
// 返回一個PlatfromView
    return DemoAView(context)
}

// 步驟2 在Flutter引擎初始化時,註冊一下步驟2建立的factory
// 這個方法是在FlutterFragment中,如果使用的是FlutterActivity,也類似
 fun configureFlutterEngine(@NonNull flutterEngine :FlutterEngine ) {
            flutterEngine
                .getPlatformViewsController()
                .getRegistry()
// 注意,這個id 需要是唯一的
                .registerViewFactory("demo_a", DemoAViewFactory());
}

然後就可以在Flutter 程式碼中去使用這個PlatformView (在Flutter 中可以使用PlatformViewLink 來簡化使用,也可以使用AndroidView UIKitView 來使用,本文使用PlatformViewLink 來做示例:

class DemoViewWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
 return PlatformViewLink(
      viewType: "demo_a",
      surfaceFactory: (context, controller) {
        if (controller is! AndroidViewController) {
          return Container(); // 或者返回一個佔位符widget
        }
        return AndroidViewSurface(
          controller: controller,
          gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
          hitTestBehavior: PlatformViewHitTestBehavior.opaque,
        );
      },
      onCreatePlatformView: (params) {
        return PlatformViewsService.initAndroidView(
          id: params.id,
          viewType: "demo_a,
          layoutDirection: TextDirection.ltr,
          creationParams: {},
          creationParamsCodec: const StandardMessageCodec(),
          onFocus: () {
            params.onFocusChanged(true);
          },
        )
          ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
          ..create();
      },
    );
  }
}

公眾號:

相關文章