PS:あなたの計画は完璧ですが、世界はあまりにも速く変化しています。
前回の記事では、Flutterでの画像の読み込みとソースコード分析について学びました。モバイル開発を行った友人はコンポーネントのライフサイクルを知っています。Flutterでも同じことが言えます。コンポーネントのライフサイクルを理解して学ぶことは非常に重要です。次のような同じシリーズの記事:
- Flutterシリーズのナビゲーターの使用に関する詳細な説明
- Flutterシリーズのフレックスレイアウトの詳細な説明
- Flutterシリーズでの画像読み込みの詳細な説明
- Flutterシリーズのウィジェットライフサイクル
- 混合開発Android記事のFlutterシリーズ
- Flutterシリーズのプラットフォームチャネルの使用に関する詳細な説明
この記事では、主に次のように、Flutterでのウィジェットのライフサイクルを紹介します。
- StatelessWidget
- StatefulWidget
- 状態ライフサイクル状態
- 状態ライフサイクル法
StatelessWidget
StatelessWidgetから派生したコンポーネントは、ステートレスコンポーネントです。ステートレスコンポーネントは、構築中に1回だけレンダリングされ、動的な変更をサポートしません。つまり、コンポーネントを他のユーザー操作で再描画することはできず、入力パラメーターを受信することによってのみ構築できます。次のように:
/// StatelessWidget
/// 表示无状态Widget
class StatelessSamplePage extends StatelessWidget {
// 外部传入数据
final String data;
StatelessSamplePage(this.data);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.lightBlue,
child: Text(data),
);
}
}
上記で渡されたパラメーターは、finalでのみ変更できます。変更しない場合、次の警告が表示されます。
This class (or a class which this class inherits from) is marked as '@immutable', but one or more of its instance fields are not final: StatelessSamplePage.data
次のように、ウィジェットが@immutableアノテーションで装飾されていることを確認します。
@immutable
abstract class Widget extends DiagnosticableTree {
現時点では、変数の変更に使用できるのはfinalのみであり、Dartでfinalによって変更された変数は、一度だけ初期化できます。これは、StatelessWidgetのステートレス特性にも準拠しています。
StatefulWidget
StatefulWidgetから派生したコンポーネントはステートフルコンポーネントであり、ステートフルコンポーネントは、動的インターフェイスのレンダリングを完了するためのデータ変更時にウィジェットの複数の構築をサポートします。現在の時刻をリアルタイムで表示するインターフェイスを実装する場合は、明らかにStatelessWidgetを完了できません。次のように、達成するステートフルStatefulWidget:
/// StatefulWidget
/// 表示有状态的 Widget
class StatefulSamplePage extends StatefulWidget {
@override
_StatefulSamplePageState createState() => _StatefulSamplePageState();
}
class _StatefulSamplePageState extends State<StatefulSamplePage> {
DateFormat _dateFormat;
String _currentTime;
Timer _timer;
@override
void initState() {
super.initState();
_dateFormat = new DateFormat("yyyy-MM-dd HH:mm:ss");
// 初始化当前时间
_currentTime = _dateFormat.format(DateTime.now());
// 更新时间
_startTime();
}
@override
Widget build(BuildContext context) {
return Center(
child: Scaffold(
appBar: AppBar(
title: Text("Stateful Widget sample"),
centerTitle: true,
),
body: Align(
alignment: Alignment.topCenter,
child: Text("当前时间:$_currentTime"),
),
),
);
}
@override
void dispose() {
super.dispose();
if(_timer!=null){
_timer.cancel();
}
}
_startTime() {
const Duration duration = Duration(seconds: 1);
_timer = Timer.periodic(
duration,
(Timer timer) => {
// 刷新界面状态
setState(() {
_currentTime = _dateFormat.format(DateTime.now());
})
});
}
}
効果は次のとおりです。
実際、静的インターフェースStatelessWidgetとStatefulWidgetのみが完全に区別できない場合、両方とも達成可能です。唯一の違いは、StatefulWidgetがsetStateメソッドを介してウィジェットの再構築をトリガーできることです。StateクラスはStateless-> Statefulのブリッジです。 。
状態ライフサイクル状態
フラッターのライフサイクルは、実際には各コンポーネントのライフサイクルです。
- StatelessWidget:ステートレスコンポーネントのライフサイクルはビルドプロセスのみです。
- StatefulWidget:ステートレスコンポーネントのライフサイクルは、状態のライフサイクルを指します。
次の図に示すように、Flutterのライフサイクルは、実際にはステートレスコンポーネントのライフサイクル、つまりステートのライフサイクルです。
上記のように、各州のライフサイクル状態は主に3つです。
- 作成済み:状態の作成状態を参照します。createStateメソッドが呼び出されると、作成済み状態になります。
- ダーティ:setStateなどのメソッドのデータが呼び出されたが、ウィジェットが再構築されていない状態を指します。
- clean:ウィジェットが構築された後の状態を指します。
- Defunct:State.disposeが呼び出された後の状態を参照します。この時点で、対応するウィジェットは破棄されており、再構築できません。
状態ライフサイクル法
ステートフルコンポーネントのライフサイクルは、ステートのライフサイクルです。特定の呼び出しプロセスとビルドトリガーのタイミングを次の図に示します。
そのライフサイクルメソッドの具体的な意味は次のとおりです。
- createState:StatefulWidgetで状態を作成するために使用されます。
- initState:変数の初期化などの状態初期化操作。
- didChangeDependencies:initStateが呼び出された後に呼び出されます。または、着用されたWidgetsコンポーネントが使用されている場合は、継承されたウィジェットをフラッター状態管理に使用できます。
- ビルド:ウィジェットの構築に使用されます。
- deactivate:このStateオブジェクトを含むウィジェットが削除された後に呼び出されます。ウィジェットが削除された後に他のウィジェットのツリー構造に追加されない場合、disposeメソッドは引き続き呼び出されます。
- dispose:メソッドが呼び出された後、ウィジェットが占有していたリソースを解放します。
- 再組み立て:開発フェーズで使用され、ホットリロード中に呼び出され、後で再構築されます。
- didUpdateWidget:親ウィジェットがビルドされるときに、子ウィジェットのdidUpdateWidgetメソッドが呼び出されます。
対応するウィジェットライフサイクルメソッドにログを追加して、上記のライフサイクルメソッドの実行を確認します。親ウィジェットのソースコードは次のとおりです。
const String TAG = "Flutter";
/// Widget生命周期
class WidgetLifecycleSamplePage extends StatefulWidget {
@override
_WidgetLifecycleSamplePageState createState() {
Log.info(TAG, "parent createState");
return _WidgetLifecycleSamplePageState();
}
}
class _WidgetLifecycleSamplePageState extends State<WidgetLifecycleSamplePage> {
num _count = 0;
@override
void initState() {
super.initState();
Log.info(TAG, "parent initState");
}
@override
Widget build(BuildContext context) {
Log.info(TAG, "parent build");
return Scaffold(
appBar: AppBar(
title: Text("Widget Lifecycle Sample"),
centerTitle: true,
),
body: Column(
children: <Widget>[
Center(
child: RaisedButton(
textColor:Colors.white,
color: Colors.lightBlue,
child: Text("parent->setState:$_count",style: TextStyle(color: Colors.white),),
onPressed: (){
setState(() {
Log.info(TAG, "parent setState");
_count++;
});
}),
),
SubWidgetLifecycleSamplePage(),
],
)
);
}
@override
void didUpdateWidget(WidgetLifecycleSamplePage oldWidget) {
super.didUpdateWidget(oldWidget);
Log.info(TAG, "parent didUpdateWidget");
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
Log.info(TAG, "parent didChangeDependencies");
}
@override
void deactivate() {
super.deactivate();
Log.info(TAG, "parent deactivate");
}
@override
void reassemble() {
super.reassemble();
Log.info(TAG, "parent reassemble");
}
@override
void dispose() {
super.dispose();
Log.info(TAG, "parent dispose");
}
}
/// 子Widget
class SubWidgetLifecycleSamplePage extends StatefulWidget {
@override
_SubWidgetLifecycleSamplePageState createState() {
Log.info(TAG, "sub createState");
return _SubWidgetLifecycleSamplePageState();
}
}
子ウィジェットの実装は親ウィジェットの実装と同様であり、投稿されません。公式アカウントのバックグラウンドでキーワード[Lifecycle]に返信すると、完成したソースコードを取得できます。
ライフサイクルの対応するメソッド呼び出しは次のとおりです。
以下のように分析します。
- ウィジェットの初期化プロセスとは、Widgeが配置されているページ、最初に親ウィジェット、次に子ウィジェットに入り、次にcreateState、initState、didChangeDepandencies、buildメソッドを順番に呼び出すライフサイクルプロセスを指します。
- 親ウィジェットseteStateがデータを更新すると、親ウィジェットの構築がトリガーされるため、子ウィジェットはdidUpdateWidgetメソッドを呼び出します。
- ホットリロードやウィジェットの破棄などの他のプロセスは、上記の状態ライフサイクルメソッドのフローチャートと同じであるため、ここでは繰り返しません。
公式アカウントのバックグラウンドでキーワード[Lifecycle]に返信すると、完成したソースコードを取得できます。詳細については、WeChat公式アカウントを参照してください。