2015-12-13 5 views
33

私は2つのフラグメントを含むアクティビティを持っています。複数のフラグメントを持つアクティビティのMVP

アクティビティ(MainActivity)は、オープン気象APIからデータを取得します。私はここで、このためにMVPを実装している: ModelはAPI
Viewからのすべての応答オブジェクトがActivity
PresenterMainPresenterMainPresenterImplMainViewGetDataInteractorGetDataInteractorImplが含まれている含まれています。

したがって、アクティビティはWebサービスからデータを取得します。両方のフラグメントには、アクティビティで取り出されたデータのデータが表示されます。

この状況でMVPを使用するベストプラクティスは何ですか?私はフラグメント間でデータを渡す方法を知っています< - >インターフェイス/コールバック経由のアクティビティ、私の質問はMVPを実装するときにこの動作の変更ですか?

+1

ちょうど考えてみましょう:フラグメントをビュー(MVPに関して)と見なしたいので、あるプレゼンターが複数のビューを参照する(または、それらのインターフェイスコールバックを参照する)ことで、最も適切なビューの異なるデータを表示することが奇妙になるのではないかと思いますそれは?プレゼンターがどのビューにどのデータを表示するかを決める必要があると思いますか?明らかに1つのビューの複数のプレゼンターが有効なアプローチなので、別の方法でもうまくいきます。http://stackoverflow.com/a/2068/1041533 – AgentKnopf

+2

@AgentKnopf実際には、ここで述べたようにhttp://programmers.stackexchange.com MVPの/ a/261351/206366では、各プレゼンターが1つのビューを提示する責任があります。プレゼンターが複数のビューを提示できる唯一の方法は、異なるビューがプレゼンターにバインドする単一のビュー・インターフェースの異なる実装であるかどうかです。 – Ari

+0

@Ariフォローアップに感謝します。それは確かに意味があります! – AgentKnopf

答えて

12

アクティビティ/フラグメントは、MVPモデルのビューとみなす必要があります。これは、データを表示し、ユーザーのやりとりを受け取るだけでよいことを意味します。 インターフェイスやコールバックを介してアクティビティやフラグメントを伝えるのは問題ありません。

ただし、APIサービスを呼び出すのはアクティビティ/フラグメントの責任ではありません。

発表者はapiサービスを呼び出す責任があります。

したがって、発表者はloadXXXのようなメソッドを公開する必要があります。内部的にはサービスを呼び出すことになります。応答が受信されると、プレゼンターはview.showXXXにサービスの結果を呼び出す必要があります。アクティビティ/フラグメントは、このloadXXXメソッドを呼び出し、showXXXを実装する必要があります。

通常、発表者はアクティビティ/フラグメントに作成または注入されます。 アクティビティ/フラグメントはプレゼンタによって公開されたインタフェースを実装しなければならず、プレゼンタはコールバックできるように、このインタフェースの弱い参照を保持します。

ユーザーが画面上で対話すると、たとえば、ボタン上のonClickの場合、アクティビティ/フラグメントはプレゼンターの対応するメソッドを呼び出します。プレゼンターはビューが読み込み中であることを示す。 view.showAsLoading()のようなものです。何かを検証したり、APIサービスからデータを読み込んだり、最終的に結果をビューにコールバックしたりする必要があります。 view.showUserDetails(userDetails)

MVPの様々な部分のコードで、例を要約する:

アクティビティ/断片は、MVPのちょうどビューを表す:

public class MyActivity extends AppCompatActivity implements MyPresenter.View { 
    private MyPresenter mPresenter; 

    public onCreate() { 
     ... 
     mPresenter = new MyPresenter(this); // Or inject it and then set the view. 
    } 

    public void onClick(View v) { 
     mPresenter.loadXXX(param1, param2); 
    } 

    // MyPresenter.View methods 

    public void showAsLoading() { 
     ... 
    } 

    public void showUserDetails(UserDetails userDetails) { 
     ... 
    } 
} 

モデル:

public class UserDetails { 
    ... 
} 

プレゼンター:

public class MyPresenter { 

    private WeakReference<MyPresenter.View> mWeakView; 

    public MyPresenter(MyPresenter.View view) { 
     mWeakView = new WeakReference(view); 
    } 

    public void loadXXX(String param1, String param2) { 
     MyPresenter.View view = mWeakView.get(); 
     if (view != null) { 
      view.showAsLoading(); 
      // Do stuff, e.g. make the Api call and finally call view.showUserDetails(userDetails); 
     } 
    } 

    interface View { 
     void showAsLoading(); 
     void showUserDetails(UserDetails userDetails); 
    } 

} 
+0

sir、なぜmWeakViewがWeakReferenceであるのか説明できますか?理由は何ですか? –

+1

これは、アクティビティ/フラグメントへの参照を保持しないようにするためです。プレゼンターはAPIに対して非同期要求を行います。プレゼンターがリクエストを行い、WeakReferenceを使用していない間にアクティビティを終了または終了すると、プレゼンターはアクティビティ/フラグメントメモリ(そのアクティビティ/フラグメントのすべてのビューとメンバーを保持)を保持します。 WeakReferenceを使用する代わりに、発表者にアタッチメソッドとデタッチメソッドを公開することも一般的です。プレゼンターをインスタンス化したら、attachメソッドを呼び出す必要があります。また、Activity/FragmentのonDestroyが呼び出されたときにdetachを呼び出す必要があります。 – fernandospr

+0

WeakReferenceやアタッチ/デタッチの手法を使用せず、発表者のリクエストが完了する前にアクティビティ/フラグメントが破棄された場合、リクエストが終了すると問題が発生する可能性があります。活動/断片。 – fernandospr

関連する問題