Flutter 3.10 に適応したシングルトン Window は非推奨になりました。View.of と PlatformDispatcher を一緒に理解しましょう

Flutter 3.10 のリリース後、そのリリースノートに「ウィンドウ シングルトン関連は廃止される予定であり、この変更は将来マルチウィンドウの関連実装をサポートするための変更です」という文が記載されていることに気づいたかもしれません

マルチ ウィンドウをサポートするための関連改善です。マルチ ウィンドウは PC シナリオでより一般的ですが、モバイル シナリオと互換性がある必要があるため、この変更は事前に行われます。

以下の図に示すように、対応する API シナリオに固有の場合、主WidgetsBinding.instance.windowMediaQueryData.fromWindowや などのインターフェイスの適応が含まれます。これは、WidgetsBinding.instance.windowが間もなく非。

適切でなくても実行できますが、アップグレードによる技術的負債は後で蓄積されます。

まず、なぜ直接WidgetsBinding.instance.window使用する。簡単に言うと、次のように要約できます。

  • いいえBuildContext、インポートしたくないですBuildContext
  • 取得したくないものは、 where の MediaQueryData影響をBuildContext。たとえば、キーボードがポップアップしたときにパディングが変更され、Scaffoldの下の

この部分については、 「あなたが知らない MediaQuery とビルド最適化の秘密」を参照してください

その後、3.10 以降、新しい API メソッドを通じて互換性WidgetsBinding.instance.windowが得られます。

  • 存在する場合はBuildContex、 を通じてView.of入手FlutterView。これが最も推奨される公式の代替手段です。
  • 取得するオブジェクトBuildContexないPlatformDispatcherviews

ここで気づきました。現在使用されているのは、オブジェクトが "Window" ではなく View と呼ばれていることですView.ofFlutterView対応するMediaQueryData.fromWindowAPI も非推奨となり、 に変更されましたMediaQueryData.fromView。この変更の根拠は次のとおりです。

当初、Flutter は 1 つのウィンドウ シナリオのみをサポートすると想定していたので、SingletonFlutterWindowそのような同時にwindow、この属性はウィンドウ自体とは関係のない多くの関数を提供します。マルチウィンドウロジック。

それでは、この二つのシーンの特徴を「長編」を使って簡単に紹介していきます。

BuildContextがあります

この調整に戻ります。最初は、次のコードに示すように、BuildContext があるシーンです。BuildContexあるView.ofする調整は次のとおりです。

/// 3.10 之前
double dpr = WidgetsBinding.instance.window.devicePixelRatio;
Locale locale = WidgetsBinding.instance.window.locale;
double width =
    MediaQueryData.fromWindow(WidgetsBinding.instance.window).size.width;


/// 3.10 之后
double dpr = View.of(context).devicePixelRatio;
Locale locale = View.of(context).platformDispatcher.locale;
double width =
    MediaQueryData.fromView(View.of(context)).size.width;

ここにView内部InheritedWidget。これFlutterViewBuildContext「ウィンドウ」と同様のパラメータ機能を提供するために共有され、View.of取得される。

  • プロパティFlutterView自体、contextバインディングの更新は通知されません。この動作は以前の動作と似ています。 WidgetsBinding.instance.window
  • 別のへの描画など、FlutterViewそれ自体が変更された場合にのみ、対応するバインディングの更新がトリガーされます。contextFlutterViewcontext

View.ofこの動作は「多」の下での更新シナリオを考慮していることがわかりますFlutterViewsizeetc以前のMediaQuery.of/を介して実装する必要がありますMediaQuery.maybeOf

Viewの場合それぞれは独立して一意である必要があります。ウィジェット ツリーでは、1 つの にのみ関連付けることができ、これは主ID の実装に反映されます。FlutterViewFlutterViewViewFlutterViewGlobalObjectKey

簡単な概要:既存のシーンでは、単に に置き換えることができによってられたシーンに対してのみ有効となるため、バインドによるBuildContexWidgetsBinding.instance.windowView.of(context)contextView.ofFlutterViewリファクタリングについて心配する必要はありません。

BuildContext が存在しません

存在しないシナリオやBuildContext使い、公式がPlatformDispatcher.viewsサポートするAPIを提供していますがget viewsMapに対応しているためオブジェクトvaluesになっているので、3.10ではないシーンどうやって適応させるIterablePlatformDispatcher.viewsBuildContextWidgetsBinding.instance.window

PlatformDispatcher内部では views、 でFlutterView使用可能な、BuildContextを使用せずにビューにアクセスするためのサポートが提供されます。

どのような状況でそうなると思いますかBuildContext? たとえば、Flutter では、次の図に示すように、3.10runApprunApp時点platformDispatcher.implicitViewデフォルトを挿入しますFlutterView

implicitViewそれは何ですか?実際、implicitViewPlatformDispatcher._viewsID が 0 のオブジェクトでありFlutterViewデフォルトでは thisオブジェクトもあります。viewsIterablefirst

つまり、 がBuildContext存在、platformDispatcher.views.firstの対応するinstance.window実装は。

/// 3.10 之前
MediaQueryData.fromWindow(WidgetsBinding.instance.window)
/// 3.10 之后
MediaQueryData.fromView(WidgetsBinding.instance.platformDispatcher.views.first)

implicitViewオブジェクトを直接使用しないのはなぜでしょうか? implicitView現在は過渡的なソリューションであるため、公式は暗黙的ビューの概念がマルチビュー シナリオに常に存在する必要はなく、アプリケーション自体が描画用のビューを提供するウィンドウの作成を積極的に要求することを望んでいます。

したがって、implicitView現在公式に提供されている_implicitViewEnabled関数については、設定可能なビットを通じてエンジンがその関数をサポートするかどうかを制御できます。implicitViewつまり、後続の更新implicitView。そのため、この関数を外部で使用すべきではなく、runApp一度したがって、アプリが起動して実行された後は決して変更されず、起動時に空の場合は常に null になります。

PlatformDispatcher.instance.views[0]前のシングルビュー シーンでは、ウィンドウの有無に関係なく、同様のものが常に存在implicitViewしますが、マルチ ウィンドウ シーンでは、PlatformDispatcher.instance.viewsウィンドウの変更に追従します。

さらにWidgetsBinding.instance.platformDispatcher.views通常、公式は Binding dependency の下でアクセスすることを推奨しているため、views直接ではなく経由でアクセスしますPlatformDispatcher.instance.viewsPlatformDispatcher

ただしrunApp()ensureInitialized()または の前に PlatformDispatcher にアクセスする必要があるシナリオを除きます。

さらに、以下の図に示すように、エンジン内のコードのウィンドウ部分の実装を通じて、必要なデフォルト ID が ID 0 に関連する基礎であることがわかります。したがって、これは互換性のロジックでもあります FlutterViewWidgetsBinding.instance.platformDispatcher.viewsによる。

やっと

最後に、ここまで言っておきますが、これは にWidgetsBinding.instance.window置き換えたView.of(context)派手な運用シナリオがまだある場合には使用できますWidgetsBinding.instance.platformDispatcher.views。その後の落とし穴を恐れない場合は、直接使用することもできますWidgetsBinding.instance.platformDispatcher.implicitView

全体的に非常に多くの説明があり、主にこの変更の背景を皆さんに理解してもらい、同時に将来のマルチウィンドウ実装の進行状況をさらに理解してもらうことを目的としています。窓口でお会いできるはずです。

さらに詳しい議論については、以下を参照してください。

  • https://github.com/flutter/flutter/issues/120306
  • https://github.com/flutter/engine/pull/39553
  • https://github.com/flutter/flutter/issues/116929
  • https://github.com/flutter/flutter/issues/99500
  • https://github.com/flutter/engine/pull/39788

おすすめ

転載: blog.csdn.net/ZuoYueLiang/article/details/130724747