Conductorライブラリは勢いを増していますが、ネットワークにはその使用に関する多くの情報がなく、公式ソースからの例のみが利用可能です。 この記事は、コンダクターの入門コースを提供し、パスからレーキを削除することを目的としています。 この記事は、すでにAndroid開発の経験がある人を対象としています。
コンダクターは、標準フラグメントの代替として配置されます。 主なアイデアは、ビューをラップして、ライフサイクルメソッドへのアクセスを提供することです。 Conductorには独自のライフサイクルがあり、フラグメントのライフサイクルよりもはるかに単純ですが、独自のトリックもあります(これについては後で詳しく説明します)。
Conductorの主な利点は次のとおりです。
- コードの簡素化
- トランザクションは即座に実行されます。
- 1つのアクティビティでアプリケーションを構築する機能
- アプリケーションアーキテクチャの選択を制限しない
- 簡単な埋め込みアニメーション
- 構成変更間で状態を維持する必要はありません
また、ボックス内にあなたが受け取ります:
- バックスタック
- 標準アクティビティコールバックは簡単に利用できます
- いくつかの標準アニメーション
- RxJavaへのライフサイクルバインディング
- ViewPagerとの迅速な統合
次に、ほとんどすべてのアプリケーションで見られるいくつかの典型的なユースケースを分析し、コントローラーのライフサイクルを理解しようとします。
パート1
公式サイトよりもさらに小さな単純な例から始めます 。 記事を読む前に、ページが大きくないことをよく理解することを強くお勧めします。
起動時に、 controller_home
レイアウトが表示される画面が表示されます。 大したことではありませんが、ここで何が起こるか見てみましょう。
コントローラのコードは非常にシンプルで、ビューを作成します。 ただし、初期化はやや複雑で、条件も含まれます。 アクティビティを作成するとき、 Conductor::attachRouter
は、ルーターをアクティビティとそのライフサイクルにバインドします。 コンテキストとコンテナに加えて、保存された状態も転送することに注意してください。すべてが正しい場合、ルーターはすべてのコントローラーをスタックとその状態に保存します。 したがって、アクティビティが再度作成されずに復元された場合、ルートコントローラーのインストールは不要です。 保存された状態から再作成されました。
このチェックを削除することを妨げるものは何もありませんが、アクティビティを作成するたびに新しいコントローラーを作成し、保存されたすべてのデータを失います。
パート2
Conductorで状態を保存する方法と場所を詳しく見てみましょう。
これを行うには、サンプルを少し複雑にする必要があります。 私たちは無駄に時間を無駄にすることはありませんが、それと同時に、私たちが人生で誰がすべきことは木を成長させることです。 タプで育てましょう。
これまでのところ、自然なことは何も起きていませんが、コントローラーが画面から削除されたときにビューがガベージコレクターによって収集されるように、 onDestroyView
ツリーイメージへのリンクをリセットしていることに注意してください。
次に、反対側からツリーを見たい場合に何が起こるか見てみましょう。 画面の向きを変えましょう。
残念ながら、ツリーは消えました。 私たちの仕事が無駄にならないようにするために何ができますか?
コントローラのライフサイクルは、アクティビティのフラグメントに関連付けられています。 フラグメントはConductor::attachRouter
内に作成され、ライフサイクルメソッドへのすべての呼び出しがそのフラグメントと初期化が実行されたアクティビティにアタッチされます。 フラグメントにはsetRetainInstance(true)
プロパティsetRetainInstance(true)
、これによりフラグメント、したがってすべてのコントローラーが構成の変更を体験できます。 したがって、私たちに必要なのは、コントローラーの変数に状態を保存することだけです。
コントローラの状態を保存するisGrown
変数と、ツリー画像の状態を更新するメソッドを追加しました。 繰り返しますが、問題はありません。
結果を見ます。
構成が変更されると、アクティビティは破棄されますが、フラグメントは破棄されません。 しかし、構成を変更するプロセスではなく、システムによってまだアクティビティが破壊されている場合はどうでしょうか? [設定にアクティビティを保存しない]をオンにして、何が起こるかを確認します。
奇跡は起こらず、すべてのデータを失いました。 この問題を解決するために、コンダクターはonRestoreInstanceState
とonRestoreInstanceState
複製しonRestoreInstanceState
。 それらを実装して、すべてが機能することを確認しましょう。
やった! ツリーが安全で健全になったので、さらに複雑なものに進むことができます。
パート3
ツリーがいくつのコーンをもたらすことができるかを調べましょう。 これを行うには、入力として円錐の数を取り、それらを表示するコントローラーを作成します。
しかし、このコードはコンパイルされません。 そして、彼は別のコンストラクターがないことを誓います-彼が必要な理由を見てみましょう。
フラグメントと同様に、ここにはトリックがあります。 フラグメントの場合、パラメーターなしのコンストラクターがリフレクションを介して呼び出されると、Bundleパラメーターを持つコンストラクターがここで呼び出されます。
コンストラクタを追加するだけの場合は。 コントローラーが破壊された場合、コンダクターはそれを再作成し、バンプに関する情報を失います。 これを回避するには、データをargs
に書き込む必要があります。 コントローラーが破壊されると、コンダクターによってArgs
が保存されます。
BundleBuilder
たよりエレガントなオプション- 例を見ることができます。
コントローラーに呼び出しを追加し、コーンの数を保存することは残っています。
最初のタパでは木を成長させ、次のタパではその上の円錐の数を示します。 最後に、別のコントローラーへの切り替えは、ルーターでpushController
を呼び出すだけでpushController
します。これにより、コントローラーがバックスタックに追加され、画面に表示されます。
すべては問題ありませんが、アプリケーションを再起動せずに戻ることはできません。修正しましょう。
このコードは、アプリケーションで問題なく機能します。 ただし、 onBackPressed
内部onBackPressed
詳しく見てみましょう。
最後のジャンプバックでアプリケーションを非表示にしたくないとします。 最初にしたいことは、 router.handleBack()
呼び出しのみを残すことです。 ただし、 handleBack
がfalseを返す場合、これは作業が行われたことを意味するものではありません。つまり、最後のコントローラーが破棄され、アクティビティ(またはルーターを含む他のコンテナー)の存在を停止する必要があることを意味します。 ルートコントローラーが削除されても、そのビューはシーンから削除されないという事実に注意する価値があります。 これは、アクティビティを終了するときに「高品質」の終了アニメーションを見ることができるように残されています。
handleBack
がfalseを返す場合、このルーターの所有者をhandleBack
必要があるという規則にhandleBack
ます。
この動作は、 false
パラメーターを指定してsetPopsLastView
メソッドを呼び出すことで変更できます。
パート4
今、果物を選ぶ時間です。 多くの場合、前のコントローラーにデータを戻すタスクがあります。 ツリーからいくつかのコーンを収集してみましょう。
リスナーをコントローラーに渡すだけでもかまいませんが、Androidエコシステムはノーと言います。 コントローラーが破壊された場合はどうなりますか? リスナーへのリンクを単に復元することはできません。 この問題を解決する最も簡単な方法は、 setTargetController
メソッドを使用することですsetTargetController
これにより、別のコントローラーへのリンクを記憶し、コントローラーの再作成時にリンクを復元できます。
コントローラのタイプを直接指定するのではなく、継承する必要があるインターフェースのみを示すことをお勧めします。
コンストラクターで、 Controller
の子孫になるパラメーターを渡し、リスナーのインターフェイスを実装します。 setTargetController
メソッドを呼び出して覚えてください。
コントローラーを離れるとき、リスナーでconesLeft(...)
を呼び出すことHomeController
、 HomeController
のコーンの数を更新します。
そして結果!
パート5
美しさをもたらすために残っています。 手首を軽くたたくと、トランジションアニメーションが追加され、コントローラーの表示と非表示が切り替わります。 ボックスには基本的なアニメーションのセットがありますが、 ControllerChangeHandler
またはそれから継承されたクラスをオーバーライドすることで、独自のアニメーションを簡単に実装することもできます。
パート6
Conductor
は、公式ドキュメントの図に示されている以外のいくつかのライフサイクルメソッドがあり、通常とは異なる動作を実装する場合に役立ちます。 それらを見てみましょう。
onAttach-コントローラーが画面に表示されるときに呼び出されます
onDetach-コントローラーが画面から削除されると呼び出されます
onDestroyView-コントローラーにバインドされたビューが破棄されると呼び出されます
onCreateView-コントローラーのビューを作成するときに呼び出されます
onDestroy-コントローラーが破棄される前に呼び出されます
以下に説明するメソッドもライフサイクルに参加しますが、 View
クラスとActivity
クラスの対応するメソッドの呼び出しを本質的に複製します。
onSaveViewState
onRestoreViewState
onSaveInstanceState
onRestoreInstanceState
次のメソッドはライフサイクル中に呼び出されますが、実際にはそれに割り当てることはできません。 呼び出しの順序は、遷移アニメーションに依存する場合があります。 そして、何も当てにしないで、アニメーションを処理するだけの価値はありません。
onChangeStarted-アニメーションの開始前に呼び出されます
onChangeEnded-アニメーションの完了時に呼び出されます
ライフサイクルを構築するとき、すべてが公式ページのようにバラ色ではありませんでした。 最終的にコントローラーの場合、2つのライフサイクルが特徴的です。 1つは、コントローラーを切り替えるときに機能する独自のサイクルと、アクティビティを破棄して作成するときに機能する2つ目のサイクルです。 それらは異なっており、それがチャートが少し成長した理由です。

ペアのメソッドが強調表示されます。 太字の矢印のアクションは、ユーザーによって開始されます。 また、パラメーターなしまたはBundle
パラメーター付きのコンストラクターのみが自動的に呼び出されることにも注意してください。 他のコンストラクタは、手動でのみ呼び出すことができます。
→ チュートリアルコード
→ 指揮者
→ ロシア語版
ウラジミール・ファラフォノフのおかげで、準備にご協力いただきありがとうございます。