ダガー2.サブコンポーネント。 ベストプラクティス。 パート2

みなさんこんにちは! 前回は、サブコンポーネントの実装と、単一画面の例でサブコンポーネントを使用する場合について考えました 。 その記事への参照がいくつかありますので、最初にそれをよく理解することをお勧めします。

今日は、アプリケーションの実際の承認済みゾーンの作成について説明し、ソーシャルネットワークと連携します。 もちろん、ダガーの助けなしではありません!

面白い? 猫へようこそ!
画像

アブストラクト

前の記事は医師と助手の抽象概念に基づいていましたが、序論で述べた事例を説明するために、より適切なものを選択することにしました。

フォーク、セマフォ、長い貨物列車がすべてある大きな駅を想像してください。 小雨が降る3番目の方法のプラットフォームでは、大勢の人が電車を待っています。 遠くでは、ビープ音が既に聞こえ、人々は突然バッグから立ち上がって、突然...待望の列車が7番街に到着します! どうやら、ドライバーは矢印を翻訳しませんでした(この例では、矢印を翻訳するのはドライバーです)。

そして、一般的に、高架を通って目的のプラットフォームに到達しても問題ありません。 反対側から7番目の経路で、商業が乗り上げるのはひどいです!

止まる


それがどのように起こるか見てみましょうか? いくつかの理由が考えられます。


実際、1つの理由しかありません-ドライバーが間違った方向に進む可能性があります。 彼は道路で長い時間を過ごしたので、各駅の物流に負担をかけるべきではありません。

ふう...運転手が矢を自分で翻訳しなくても、 駅員が彼のためにそれをするのはまったく同じことです

しかし、認可されたゾーンはそれと何の関係がありますか?

少し痛み

タスクに直面していると仮定します:承認されたユーザーにはアニメーションが表示され、匿名の作成者には別のアニメーションが表示されます。 このロジックを実装するほとんどのアプリケーションでは、次のようなものが表示されます。

if (userIsAuthourized) { //    ,  . doSomething(); showAnimation(); } else { // doOtherthing(); showOtherAnimation(); } 

そして、あなたは何度も表示されます:(
画像

最良の場合、各画面のコピーが2つあり、認証状態に「依存」します。 主な機能を実装する共通の祖先を持つ。 そして、これはビジネスロジックには深く入り込んでいない...

私が何をしているのか、あなたはすでに推測しているかもしれません。

この状況をステーションに転送すると、 ドライバー (ソフトウェアコンポーネント) は、到着する方法 (表示するアニメーション)を個別に選択します。

そして、ここでは、そのような実装は許可されたゾーンではないことを理解することが重要です(序文で「本物」という言葉を強調した理由)。 「ゾーン」とは、現在のオブジェクト(または状態)から1つの特定の機能(ユーザー定義または匿名)のみが利用可能であることを意味します。 この実装では、オブジェクト自体が何に向けるかを決定し、理論的には、ある「ゾーン」から別の「ゾーン」の機能に切り替えることができます。 それは間違っています。

そして再び、これは私たちのコンポーネントにはないはずのロジックです。
画像

変更の時間

機能、メソッド、またはコードの一部をクラスに移動して、将来そのオブジェクトを提供または置換できるようにすることができます。 UserAnimationFunctionとAnonymousAnimationFunctionのアニメーションをそれぞれ取り出します。 さて、すでに方法がわかっているので、注入します。

コンバージョン1

 @Inject UserAnimationFunction userAnimationFunction; @Inject AnonymousAnimationFunction anonymousAnimationFunction; 

もちろん、私たちはまだ不運な状態のままではありません。

 if (userIsAuthourized) { userAnimationFunction.show(); } else { anonymousAnimationFunction.show(); } 

正しい考え:

運転手は、到着したことを通知するだけでよく、すでに駅員は彼のために特定の道を準備します。

(と同じ)

ソフトウェアコンポーネントは、アニメーションを表示する必要があることを示す必要があります。アニメーションを担当するオブジェクトは、アニメーションを決定します。

それはインターフェースに他なりません。 アニメーション用の単一のインターフェイスを定義します。

 public interface AuthDependentAnimationFunction { void show(); } 

それから私たちに残っているのは、私たちのために道を選ぶステーションのまさにその労働者を呼ぶことです。 コンポーネントが思い浮かぶはずです:

変換2

 @Inject AuthDependentAnimationFunction animationFunction; ... animationFunction.show(); 

「どうやって?」と聞いて

すべての魔法は、サブコンポーネントの助けを借りて可能になります。 ご存知のように、前回の記事ではサブ画面を使用して、各画面に独自の依存関係グラフを作成しました。 このようなグラフの寿命は、画面の寿命に依存していました。

この場合、2つの依存関係グラフがあります。1つは承認済みゾーン用、もう1つは匿名用です。 ライフタイムが許可の時間に依存することを推測することは難しくありません。

多くの場合、APIリクエストにはユーザートークンが含まれているため、このトークンを承認済みグラフのコアとして使用できます。

匿名グラフの場合は、カーネルを省略できます(好みに応じて、許可されたカーネルのカーネルも省略できます)。

概略的に、システムは次のようになります。
画像

おそらくAuthDependentComponentインターフェイスに気づいたでしょう。 インターフェイスを使用して、ソフトウェアコンポーネントでは、1つを除くすべてのロジック選択ケースを取り除きました。 ロジックの選択は、注入用コンポーネントの選択に帰着しました。

 if (userIsAuthourized) { App.getInstance().getUserComponent.inject(); } else { App.getInstance().getAnonymousComponent.inject(); } 

また、2つのサブコンポーネントに共通のAuthDependentComponentインターフェイスを使用すると、このコードも削除できます。

 public interface AuthDependentComponent { void inject(SomeFragment fragment); } 

注意してください。 AuthDependentComponentは、「コンポーネント」、「サブコンポーネント」などの注釈のない単なるインターフェースです。 2つのコンポーネントの共通の祖先としてのみ必要です。 また、その中に注入メソッドを記述することもできます-Daggerは、コンポーネントの相続人ごとにそれらを実装します。

 @UserScope @Subcomponent(modules = UserModule.class) public interface UserComponent extends AuthDependentComponent { } @Module public class UserModule { private String userToken; public UserModule(String userToken) { this.userToken = userToken; } @UserScope @Provides AuthDependentAnimationFunction provideAnimationFunction() { return new UserAnimationFunction(); } } @AnonymousScope @Subcomponent(modules = AnonymousModule.class) public interface AnonymousComponent extends AuthDependentComponent { } @Module public class AnonymousModule { @AnonymousScope @Provides AuthDependentAnimationFunction provideAnimationFunction() { return new AnonymousAnimationFunction(); } } @Singletone @Component(modules = AppModule.class) public interface AppComponent { UserComponent userComponent(UserModule userModule); AnonymousComponent anonymousComponent(AnonymousModule anonymousModule); } 

承認の現在の状態を知っている唯一の責任者は、ステーションクラスのアプリクラスです。

 public class App extends Application { private AuthDependentComponent authDependentComponent; ... private void init() { ... onUserLoggedIn(); } public void onUserLoggedIn(String userToken) { authDependentComponent = appComponent.userComponent(new UserModule(userToken)); } public void onUserLoggedOut() { authDependentComponent = appComponent.anonymousComponent(new AnonimousModule()); } public AuthDependentComponent getAuthDependentComponent() { return authDependentComponent; } } 

その結果、画面は次のようになります。

 @Inject AuthDependentAnimationFunction animationFunction; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); App.getInstance().getAuthDependentComponent().inject(this); } public void showAnimation() { animationFunction.show(); } 

ゾーン間の移行について

私の実践では、許可の状態を変更するときに、すべてのアプリケーションコンポーネントが完全に再作成されるのを見てきました。 原則として、これは正常です。 多くの場合、ゾーンの違いは重要です。 再作成の場合、新しく作成された画面は、対応するゾーンからすでに依存関係を受け取ります。 コードを改善する必要はありません。

ロジックがロジックのわずかな違いに対応している場合、依存関係の再注入に注意を払うことができます。 本質的に、認証状態を変更するときは、ソフトウェアコンポーネントに単にinject()を強制します。

 App.getInstance().getAuthDependentComponent().inject(this); 

したがって、以前に作成された古いコンポーネントの依存関係は、新しいコンポーネントの依存関係によって上書きされます。
画像

ボーナス


私はソーシャルネットワークについて何か言ったと思う?

問題は、さまざまなソーシャルネットワークの開発者がAPIを実装していることです。 一度に複数のソーシャルネットワークをサポートしようとした人は知っています。 ただし、これらのAPIのメソッドの本質はほぼ同じです。

-投稿の公開。
-写真の公開。
-ステータスの変更。
-など

すべてを美しくするために、認可されたゾーンを例に取り、各ソーシャルネットワークが個別のゾーンであると想像してください。 したがって、各ゾーンには、ユーザーが許可されているソーシャルネットワークに応じて提供される独自のコンポーネントがあります。 また、APIの操作は、上記の機能を備えたインターフェイスを介して行われ、各ソーシャルネットワークにさまざまな方法で実装されます。 やるだけ! :)

GitHubでソーシャルネットワークを使用した作業を実装する例

合計2つの記事


Daggerが役立つコードのセクションを見つけるにはどうすればよいですか?


一般的に、DaggerとDependency Injectionパターンを理解する上で皆さんの幸運を祈ります。
コメントに興味深い事例やタスクを書いてください。

Source: https://habr.com/ru/post/J337070/


All Articles