2016-09-30 4 views
1

Я создаю приложение для Android с использованием шаблона MVP. Для инъекции зависимости я использую кинжал 2. У меня есть абстрактный фрагмент, который реализует интерфейс «view», делая его вид в Model-View-Presenter.Подкласс презентатора для просмотра андроида

public abstract class MediaDetailFragment extends Fragment implements DetailsMvpView { 
private static final String RESOURCE = "resource"; 
private static final String POSTER_SIZE = "w342/"; 


@Inject DetailPresenter mDetailPresenter; 
@Inject CreditPresenter mCreditPresenter; 
@BindView(R.id.media_image_flipper) ControllableFlipper mImageFlipper; 
@BindView(R.id.keyword_recyclerview) RecyclerView mKeywordRecyclerView; 
@BindView(R.id.title_textview) TextView mTitleTextView; 
@BindView(R.id.overview_content_textview) TextView mOverviewTextView; 
@BindView(R.id.cast_recyclerview) CreditRecyclerView mCastRecyclerView; 
@BindView(R.id.crew_recyclerview) CreditRecyclerView mCrewRecyclerView; 
@BindView(R.id.empty_view) TextView mRecyclerviewEmpty; 
@BindView(R.id.button_share) ImageButton mShare; 
@BindView(R.id.button_trailers) ImageButton mTrailers; 
@BindView(R.id.button_reviews) ImageButton mReviews; 
@BindBool(R.bool.isTablet) boolean mIsTablet; 

@OnClick(R.id.button_share) public void shareMedia(View view) { 
    startActivity(new Intent(Intent.ACTION_SEND) 
      .putExtra(Intent.EXTRA_TEXT, getActivity().getString(R.string.base_youtube_url) 
        + POSTER_SIZE + mMedia.posterPath() + "\n\n" 
        + mMedia.title() + "\n\n" + mMedia.overview()) 
      .setType("text/plain")); 
} 

@OnClick(R.id.button_trailers) public void requestTrailers(View view) { 
    mDetailPresenter.loadMovies(mMedia.id()); 
} 

@OnClick(R.id.button_reviews) public void requestReviews(View view) { 
    if (NetworkUtil.isNetworkConnected(getContext())) { 
     ((FragmentHandler) getActivity()).onReviewsRequested(mMedia); 
    } else { 
     ViewUtil.displayNoNetworkSnackbar(getActivity()); 
    } 
} 

private Media mMedia; 
private DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 
private OnGlobalLayoutListener mListener; 

@Override 
public void onCreate(@Nullable Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    mMedia = getArguments().getParcelable(RESOURCE); 
} 

@Nullable 
@Override 
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 

    View rootView = inflater.inflate(R.layout.media_details_fragment, container, false); 

    ((BaseActivity) getActivity()).activityComponent().inject(this); 
    ButterKnife.bind(this, rootView); 

    getActivity().getWindowManager().getDefaultDisplay().getMetrics(mDisplayMetrics); 

    mTitleTextView.setText(mMedia.title()); 
    mOverviewTextView.setText(mMedia.overview()); 

    mKeywordRecyclerView.setAdapter(new KeywordAdapter(getContext())); 
    mCastRecyclerView.setAdapter(R.layout.item_credit_normal, mRecyclerviewEmpty); 
    mCrewRecyclerView.setAdapter(R.layout.item_credit_normal, mRecyclerviewEmpty); 

    mListener =() -> rootView.post(() -> { 
     if (mIsTablet) { 
      mImageFlipper.getLayoutParams().height = 
        ViewUtil.setHeightForAspectRatio(rootView.getWidth(), ViewUtil.STANDARD); 
     } else { 
      mImageFlipper.getLayoutParams().height = 
        ViewUtil.setHeightForAspectRatio(mDisplayMetrics.widthPixels, ViewUtil.STANDARD); 
     } 
     rootView.getViewTreeObserver().removeOnGlobalLayoutListener(mListener); 
    }); 
    rootView.getViewTreeObserver().addOnGlobalLayoutListener(mListener); 

    return rootView; 
} 

@Override 
public void onStart() { 
    super.onStart(); 

    mDetailPresenter.attachView(this); 
    mDetailPresenter.loadImages(mMedia.id()); 
    mDetailPresenter.loadKeywords(mMedia.id()); 

    mCreditPresenter.attachCastView(mCastRecyclerView); 
    mCreditPresenter.attachCrewView(mCrewRecyclerView); 
    mCreditPresenter.loadCredits(mMedia.id()); 
} 

@Override 
public void onStop() { 
    mDetailPresenter.detachView(); 
    mCreditPresenter.detachCastView(); 
    mCreditPresenter.detachCrewView(); 
    super.onStop(); 
} 

@Override 
public void showImages(String image) { 
    mImageFlipper.addImagePath(image); 
} 

@Override 
public void showKeywords(List<String> keywords) { 
    ((KeywordAdapter) mKeywordRecyclerView.getAdapter()).setKeywords(keywords); 
} 

@Override 
public void showVideos(List<Video> videos) { 
    TrailerDialogFragment.newInstance(videos).show(getFragmentManager(), null); 
} 

@Override 
public void showError() { 
    if (!NetworkUtil.isNetworkConnected(getContext())) { 
     ViewUtil.displayNoNetworkSnackbar(getActivity()); 
    } 
} 
} 

В зависимости от ситуации я буду использовать один из двух подклассов этого абстрактного вида. Как вы можете видеть, я вставляю «DetailsPresenter» в представление. DetailsPresenter также является абстрактным классом с двумя подклассами (по одному для каждого подкласса представления).

Однако, если представление является MovieDetailFragment, оно должно иметь MovieDetailPresenter, и если оно является ShowDetailFragment, оно должно иметь ShowDetailPresenter.

Мой вопрос: где я должен реализовывать логику для проверки того, что это за вид, и предоставления правильного DetailsPresenter? Должен ли я сделать это в модуле Dagger (возможно, в методе, который возвращает презентатора)? Должен ли я делать это в самом фрагменте?

Это мой модуль:

@Module 
public class ConfigPersistentModule { 

    @Provides 
    DetailPresenter provideDetailPresenter(DataManager dataManager) { 
     return new MovieDetailPresenter(dataManager); 
    } 
} 

Пожалуйста, помогите мне.

ответ

1

Вы должны вводить свой выступающий в дочерних классах (MovieDetailFragment & ShowDetailFragment) и в модуле необходимо иметь два обеспечить модуль, как показано ниже:

@Module 
public class ConfigPersistentModule { 

@Provides 
MovieDetailFragment provideDetailPresenter(DataManager dataManager) { 
    return new MovieDetailPresenter(dataManager); 
} 

@Provides 
ShowDetailFragment provideDetailPresenter(DataManager dataManager) { 
    return new ShowDetailFragment(dataManager); 
} 
} 

, а затем в ваших дочерних классах впрыснуть так:

в ShowDetailFragment:

@Inject ShowDetailFragment mCreditPresenter; 

в MovieDetailFragment:

@Inject MovieDetailFragment mCreditPresenter; 

теперь отца вашего класса (MediaDetailFragment) поставить абстрактную функцию под названием «getPresenter», который является обязательным для детей, чтобы заменить его, как показано ниже:

public abstract class MediaDetailFragment extends Fragment implements DetailsMvpView { 
    private mDetailPresenter; 

    public abstract DetailPresenter getPresenter(); 

    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 
     this.mDetailPresenter = getPresenter(); 
     ... 
     ... 
    } 
    ... 
    ... 
} 

теперь каждый класс, реализующий MediaDetailFragment должны рассказать отец о своем ведущем и отец использует этого ведущего. поэтому в классах детей (MovieDetailFragment & ShowDetailFragment) пишут:

@Override 
public DetailPresenter getPresenter() 
{ 
    return mCreditPresenter; 
} 
+0

Хех, наконец, я в конечном итоге реализации именно то, что вы сказали. Понял, что я понял. Поскольку ваш ответ правильный, +1 и принимайте! –

+0

хорошо jub !! его лучше, когда вы сделаете это сами, потому что вы никогда не забудете концепцию. и я даю вам голосование, потому что ваш вопрос заставил меня подумать;) –

 Смежные вопросы

  • Нет связанных вопросов^_^