Flutter 3.10 のリリース後、そのリリースノートに「ウィンドウ シングルトン関連は廃止される予定であり、この変更は将来マルチウィンドウの関連実装をサポートするための変更です」という文が記載されていることに気づいたかもしれません。
マルチ ウィンドウをサポートするための関連改善です。マルチ ウィンドウは PC シナリオでより一般的ですが、モバイル シナリオと互換性がある必要があるため、この変更は事前に行われます。
以下の図に示すように、対応する API シナリオに固有の場合、主WidgetsBinding.instance.window
にMediaQueryData.fromWindow
や などのインターフェイスの適応が含まれます。これは、WidgetsBinding.instance.window
が間もなく非。
適切でなくても実行できますが、アップグレードによる技術的負債は後で蓄積されます。
まず、なぜ直接WidgetsBinding.instance.window
使用する。簡単に言うと、次のように要約できます。
- いいえ
BuildContext
、インポートしたくないですBuildContext
- 取得したくないものは、 where の
MediaQueryData
影響をBuildContext
。たとえば、キーボードがポップアップしたときにパディングが変更され、Scaffold
の下の
その後、3.10 以降、新しい API メソッドを通じて互換性WidgetsBinding.instance.window
が得られます。
- 存在する場合は
BuildContex
、 を通じてView.of
入手FlutterView
。これが最も推奨される公式の代替手段です。 - 取得するオブジェクトが
BuildContex
ないPlatformDispatcher
views
ここで気づきました。現在使用されているのは、オブジェクトが "Window" ではなく View と呼ばれていることですView.of
。FlutterView
対応するMediaQueryData.fromWindow
API も非推奨となり、 に変更されました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
。これFlutterView
はBuildContext
「ウィンドウ」と同様のパラメータ機能を提供するために共有され、View.of
取得される。
- プロパティ
FlutterView
自体、context
バインディングの更新は通知されません。この動作は以前の動作と似ています。WidgetsBinding.instance.window
- 別のへの描画など、
FlutterView
それ自体が変更された場合にのみ、対応するバインディングの更新がトリガーされます。context
FlutterView
context
View.of
この動作は「多」の下での更新シナリオを考慮していることがわかりますFlutterView
。 size
etc以前のMediaQuery.of
/を介して実装する必要がありますMediaQuery.maybeOf
。
View
の場合、それぞれは独立して一意である必要があります。ウィジェット ツリーでは、は1 つの にのみ関連付けることができ、これは主にID の実装に反映されます。FlutterView
FlutterView
View
FlutterView
GlobalObjectKey
簡単な概要:既存のシーンでは、単に に置き換えることができ、によってられたシーンに対してのみ有効となるため、バインドによるBuildContex
WidgetsBinding.instance.window
View.of(context)
context
View.of
FlutterView
リファクタリングについて心配する必要はありません。
BuildContext が存在しません
存在しないシナリオやBuildContext
使い、公式がPlatformDispatcher.views
サポートするAPIを提供していますがget views
、Map
に対応しているためオブジェクトvalues
になっているので、3.10ではないシーンにどうやって適応させる?Iterable
PlatformDispatcher.views
BuildContext
WidgetsBinding.instance.window
PlatformDispatcher
内部ではviews
、 でFlutterView
使用可能な、BuildContext
を使用せずにビューにアクセスするためのサポートが提供されます。
どのような状況でそうなると思いますかBuildContext
? たとえば、Flutter では、次の図に示すように、3.10runApp
のrunApp
時点platformDispatcher.implicitView
デフォルトを挿入しますFlutterView
。
implicitView
それは何ですか?実際、implicitView
はPlatformDispatcher._views
ID が 0 のオブジェクトであり、FlutterView
デフォルトでは thisのオブジェクトもあります。views
Iterable
first
つまり、 が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.views
PlatformDispatcher
ただし
runApp()
、ensureInitialized()
または の前に PlatformDispatcher にアクセスする必要があるシナリオを除きます。
さらに、以下の図に示すように、エンジン内のコードのウィンドウ部分の実装を通じて、必要なデフォルト ID が ID 0 に関連する基礎であることがわかります。したがって、これは互換性のロジックでもあります FlutterView
。WidgetsBinding.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