Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

AndroidMVPHelper

67 views

Published on

Nikita Sizintsev

Published in: Technology
  • Be the first to comment

  • Be the first to like this

AndroidMVPHelper

  1. 1. AndroidMVPHelper MVP на стероидах
  2. 2. Цели проекта • Упростить интеграцию MVP паттерна; • Избавиться от написания “рутинного” кода; • Добавить дополнительный функционал.
  3. 3. Что такое MVP View Presenter Model ● Представление (View) — реализует отображение данных, обращается к представителю за обновлениями; ● Представитель (Presenter) — реализует взаимодействие между моделью и представлением. ● Модель (Model) — содержит в себе бизнес-логику, получает данные из хранилища.
  4. 4. Модули base_mvp mvp mvp_presenter mvp_rx2_presenter mvp_list mvp_autosavable mvp_autosavable_annotation mvp_view_wrap mvp_view_wrap_annotation
  5. 5. Модуль mvp Основные классы: • BaseMvpActivity • BaseMvpFragment • BaseMvpDialogFragment Возможности: • Управление жизненным циклом компонентов • Установка лейаута и инъекция вью-полей • Зануление вью-полей • LifeCycleObservable
  6. 6. Модуль mvp. 
 Имплементация. MVP component IViewState IPresenter Models
  7. 7. Модуль mvp. Имплементация. ViewState. public class ViewState implements IViewState<ViewState.IViewStateView> {
 public void save(@NotNull Bundle bundle) public void restore(@NotNull Bundle bundle) public void apply(@NotNull IViewStateView iViewStateView) 
 public interface IViewStateView {
 //Methods to provide data from ViewState to View
 }
 
 }

  8. 8. Модуль mvp. Имплементация. Presenter. public class Presenter extends BaseAsyncPresenter<Presenter.IPresenterView> {
 //BaseAsyncExecutorPresenter<Presenter.IPresenterView>
 //BaseAsyncRxSchedulerPresenter<Presenter.IPresenterView>
 //IAsyncPresenter<Presenter.IPresenterView>
 //IPresenter<Presenter.IPresenterView>
 
 
 public interface IPresenterView extends BaseAsyncPresenter.ITaskListener {
 //Methods to provide data from View to Presenter and backwards.
 }
 
 }
  9. 9. Модуль mvp. Имплементация. Presenter. interface IPresenter<in T> {
 
 fun onAttachView(view: T)
 
 fun onDetachView()
 
 }
  10. 10. Модуль mvp. Имплементация. Presenter. interface IAsyncPresenter<in T : IAsyncPresenter.ITaskListener> : IPresenter<T> {
 
 fun cancel()
 
 interface ITaskListener {
 
 fun onTaskStatusChanged(taskId: Int, status: Int)
 
 }
 
 }

  11. 11. Модуль mvp. Имплементация. Presenter. open class BaseAsyncPresenter<T : IAsyncPresenter.ITaskListener> : BasePresenter<T>(), IAsyncPresenter<T> { fun <T> execute(callable: Callable<T>, executor: AbstractExecutorService, id: Int): Future<T> fun execute(runnable: Runnable, executor: AbstractExecutorService, id: Int): Future<Unit>
  12. 12. Модуль mvp. Имплементация. Presenter. fun waitForViewIfNeeded(): T protected fun checkIfInterruptedException(ex: Throwable?): Boolean 
 protected fun isInMainThread(): Boolean protected inline fun postOnMainThread(crossinline body: () -> Unit)
  13. 13. Модуль mvp. Имплементация. Presenter. protected fun notifyTaskAdded(task: Int) protected fun notifyTaskFinished(task: Int) fun isTaskRunning(task: Int): Boolean fun isAnyOfTasksRunning(vararg tasks: Int): Boolean fun hasRunningTasks(): Boolean
  14. 14. Модуль mvp. Имплементация. Presenter. abstract class BaseAsyncExecutorPresenter<T : IAsyncPresenter.ITaskListener> : BaseAsyncPresenter<T>(), IAsyncPresenter<T> { protected abstract fun createExecutor(): ThreadPoolExecutor fun <T> execute(callable: Callable<T>, id: Int): Future<T> fun execute(runnable: Runnable, id: Int): Future<Unit> protected fun useSaveThreadFactory(): Boolean = true
  15. 15. Модуль mvp. Имплементация. Presenter. abstract class BaseAsyncRxSchedulerPresenter<T : IAsyncPresenter.ITaskListener> : BaseAsyncExecutorPresenter<T>() { fun <T> execute(observable: Observable<T>,
 subscribeOn: Scheduler,
 observeOn: Scheduler,
 id: Int,
 onNext: Consumer<T>? = null,
 onError: Consumer<Throwable>? = null,
 onComplete: Action? = null,
 provideInterruptedException: Boolean = false): Disposable
  16. 16. Модуль mvp. Имплементация. Presenter. fun <T> execute(observable: Observable<T>,
 taskId: Int,
 onNext: Consumer<T>? = null,
 onError: Consumer<Throwable>? = null,
 onComplete: Action? = null,
 provideInterruptedException: Boolean = false): Disposable
  17. 17. Модуль mvp. Имплементация. View. public interface IView extends Presenter.IPresenterView, ViewState.IViewStateView { //Other methods }
  18. 18. Модуль mvp. Имплементация. Activity. public class Activity extends BaseMvpActivity<IView, Presenter, ViewState> implements IView { public IView getMvpView() { return this;} public ViewState createViewState() { return new ViewState();} public Presenter createPresenter() { return new Presenter();} public void createView() public void onInitialized(Presenter presenter, ViewState viewState) public void onTaskStatusChanged(int taskId, int status) }
  19. 19. Модуль mvp. Имплементация. Fragment. public class Fragment extends BaseMvpFragment<IView, Presenter, ViewState> implements IView { public IView getMvpView() { return this;} public ViewState createViewState() { return new ViewState();} public Presenter createPresenter() { return new Presenter();} public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) public void onInitialized(Presenter presenter, ViewState viewState) public void onTaskStatusChanged(int taskId, int status) }
  20. 20. Модуль mvp. 
 Сохранение компонентов. public class Fragment extends BaseMvpFragment<IView, Presenter, ViewState> implements IView { @Override
 public boolean retainPresenter() {
 return true;
 }
 
 @Override
 public boolean retainViewState() {
 return true;
 } }
  21. 21. Модуль mvp. 
 Вью инъекция и зануление. @Layout(R.layout.fragment_layout)
 public class Fragment extends BaseMvpFragment<IView, Presenter, ViewState> implements IView {
 
 @InjectView(R.id.text_view)
 protected TextView textView;
 
 @Override
 public boolean nullViews() {
 return true;
 }
 
 }
  22. 22. Activity • ON_CREATE • ON_START • ON_RESUME • ON_PAUSE • ON_STOP • ON_SAVE_INSTANCE • ON_DESTROY Fragment • ON_ATTACH • ON_CREATE • ON_VIEW_CREATED • ON_ACTIVITY_CREATED • ON_START • ON_RESUME • ON_PAUSE • ON_STOP • ON_SAVE_INSTANCE • ON_DESTROY_VIEW • ON_DESTROY • ON_DETACH Модуль mvp. Подписка на жизненный цикл.
  23. 23. Модуль mvp. Подписка на жизненный цикл. Activity. object ActivityLifecycle { //Constants for supported activity lifecycle events @Target(AnnotationTarget.FUNCTION)
 @Retention(AnnotationRetention.RUNTIME)
 @Inherited
 annotation class OnLifecycleEvent(@ActivityEvent val event: Int) }
  24. 24. Модуль mvp. Подписка на жизненный цикл. Fragment. object FragmentLifecycle { //Constants for supported fragment lifecycle events @Target(AnnotationTarget.FUNCTION)
 @Retention(AnnotationRetention.RUNTIME)
 @Inherited
 annotation class OnLifecycleEvent(@FragmentEvent val event: Int) }
  25. 25. Модуль mvp. Подписка на жизненный цикл. public class CameraManager {
 
 @FragmentLifecycle.OnLifecycleEvent(event = FragmentLifecycle.ON_VIEW_CREATED)
 public void onViewCreated()
 
 @FragmentLifecycle.OnLifecycleEvent(event = FragmentLifecycle.ON_VIEW_CREATED)
 public void onViewCreated(Fragment fragment)
 
 @FragmentLifecycle.OnLifecycleEvent(event = FragmentLifecycle.ON_VIEW_CREATED)
 public void onViewCreated(Fragment fragment, View view)
 
 @FragmentLifecycle.OnLifecycleEvent(event = FragmentLifecycle.ON_VIEW_CREATED)
 public void onViewCreated(Fragment fragment, View view, Bundle savedInstance)
 
 }

  26. 26. Модуль mvp. Подписка на жизненный цикл. public class Fragment extends BaseMvpFragment<IView, Presenter, ViewState> implements IView { private CameraManager cameraManager;
 
 public Fragment() {
 cameraManager = new CameraManager();
 subscribe(cameraManager);
 } } 

  27. 27. Модуль mvp_autosavable. Назначение: • Сохранение полей ViewState в Bundle и восстановление их оттуда.
  28. 28. Модуль mvp_autosavable. Использование. @AutoSavable(includeSuper = false)
 public class ViewState implements IViewState<ViewState.IViewStateView> {
 
 private ArrayList<Integer> integers;
 
 @Ignore
 private boolean ignoredField = false;
 
 public ArrayList<Integer> getIntegers() {
 return integers;
 }
 
 public void setIntegers(ArrayList<Integer> integers){
 this.integers = integers;
 }

  29. 29. Модуль mvp_autosavable. Использование. @Override
 public void save(@NotNull Bundle bundle) {
 ViewStateSaver.save(this, bundle);
 }
 
 @Override
 public void restore(@NotNull Bundle bundle) {
 ViewStateSaver.restore(this, bundle);
 } }
  30. 30. Модуль mvp_autosavable. Сгенерированный класс. public final class ViewStateSaver { 
 public static void save(ViewState state, Bundle inState) {
 inState.putSerializable("integers", (Serializable) state.getIntegers());
 }
 
 public static void restore(ViewState state, Bundle outState) {
 state.setIntegers((ArrayList<Integer>) outState.getSerializable("integers"));
 } 
 }
  31. 31. Модуль mvp_view_wrap. Назначение: • Упрощает вызов методов в главном потоке из рабочих потоков; • Позволяет вызывать методы в главном потоке, синхронно с работающим.
  32. 32. Модуль mvp_view_wrap. Использование. @Wrap
 public interface IView extends Presenter.IPresenterView, ViewState.IViewStateView {
 
 void foo();
 
 Object bar();
 
 @Ignore
 void ignoredMethod();
 
 }
  33. 33. Модуль mvp_autosavable. Сгенерированный класс. public final class IViewWrap implements IView { private final IView wrappedView;
 
 private final Handler mainHandler = new Handler((Looper.getMainLooper()));
 
 public IViewWrap(IView wrappedView) {
 this.wrappedView = wrappedView;
 }
  34. 34. Модуль mvp_autosavable. Сгенерированный класс. foo() final Object lockObject = new Object();
 synchronized(lockObject) {
 mainHandler.post(new Runnable() {
 @Override
 public void run() {
 wrappedView.foo();
 synchronized(lockObject) {
 lockObject.notify();
 }}
 });
 try {
 lockObject.wait();
 } catch (InterruptedException ex) {
 ex.printStackTrace();
 throw new RuntimeException(ex);
 }
 }
  35. 35. Модуль mvp_autosavable. Сгенерированный класс. bar() final Object lockObject = new Object();
 final Object[] returnValueArray = new Object[1];
 synchronized(lockObject) {
 mainHandler.post(new Runnable() {
 @Override
 public void run() {
 returnValueArray[0] = wrappedView.bar();
 synchronized(lockObject) {
 lockObject.notify();
 }}
 });
 try {
 lockObject.wait();
 } catch (InterruptedException ex) {
 ex.printStackTrace();
 throw new RuntimeException(ex);
 }
 }
 return (Object) returnValueArray[0];
  36. 36. Модуль mvp_autosavable. Сгенерированный класс. ignoredMethod() public void ignoredMethod() {
 wrappedView.ignoredMethod();
 }
  37. 37. Модуль mvp_view_wrap. Использование. public class Activity
 extends BaseMvpActivity<IView, Presenter, ViewState>
 implements IView {
 
 private IViewWrap wrap = new IViewWrap(this);
 
 @NotNull
 @Override
 public IView getMvpView() {
 return wrap;
 }
  38. 38. Модуль mvp_list. Быстрая имплементация экранов со списком на основе RecyclerView c • Пейджингом • Поиском • Swipe to refresh • Прогресс бары в списке и на весь экран • Заглушки «нет контента» и «произошла ошибка»
  39. 39. Модуль mvp_list. MVP component IViewState IPresenter Models Delegate
  40. 40. Модуль mvp_list. Имплементация. IPagingResponse. interface IPagingResponse<I> {
 
 val data: MutableList<I>
 
 val canLoadMore: Boolean
 
 }
  41. 41. Модуль mvp_list. Имплементация. ViewState. public class PagingViewState extends BasePagingSearchableViewState<AwesomeEntity, PagingViewState.IViewStateView> {
 public List<AwesomeEntity> getItems()
 
 public void setItems(@Nullable List<AwesomeEntity> list)
 
 public void save(@NotNull Bundle out)
 
 public void restore(@NotNull Bundle inState)
 
 public interface IViewStateView extends BasePagingSearchableViewState.IViewStateView<AwesomeEntity>
 
 }
  42. 42. Модуль mvp_list. Имплементация. ViewState. abstract class BasePagingSearchableViewState<I, in V : BasePagingSearchableViewState.IViewStateView<I>> : IViewState<V> { companion object {
 @JvmField val NO_ERROR_CODE = -1
 }
 
 var query = ""
 
 abstract var items: MutableList<I>?
 
 var canLoadMore = false
 
 var nextPageFailed = false
 
 var errorCode = NO_ERROR_CODE
  43. 43. Модуль mvp_list. Имплементация. ViewState. interface IViewStateView<I> {
 
 fun setQuery(query: String)
 
 fun setItems(items: MutableList<I>, canLoadMore: Boolean, isSearch: Boolean)
 
 fun setNextPageLoadFailed(code: Int)
 
 fun setFirstPageLoadFailed(code: Int)
 
 }
  44. 44. Модуль mvp_list. Имплементация. Presenter. public class PagingPresenter extends BaseAsyncRxSchedulerPresenter<PagingPresenter.IPresenterView> implements IPagingSearchablePresenter { fun isFirstPageLoading(): Boolean
 
 fun isNextPageLoading(): Boolean
 
 fun cancelFirstPages()
 
 fun cancelNextPages()
 
 fun cancelAllPageRequests()
  45. 45. Модуль mvp_list. Имплементация. Presenter. public interface IPresenterView extends IPagingSearchablePresenter.IPresenterView<AwesomeEntity, PagingResponse<AwesomeEntity>> {
 fun onFirstPageLoaded(response: PR)
 
 fun onNextPageLoaded(response: PR)
 
 fun onNextPageLoadFailed(code: Int)
 
 fun onFirstPageLoadFailed(code: Int) 
 }
  46. 46. Модуль mvp_list. Имплементация. Adapter. public class PagingAdapter
 extends BasePagingAdapter<AwesomeEntity, PagingAdapter.PagingAdapterListener> {
 
 @Override
 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
 
 @Override
 public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
 
 public interface PagingAdapterListener extends BasePagingAdapter.AdapterListener {
 
 }
 
 }

  47. 47. Модуль mvp_list. Имплементация. Adapter. interface AdapterListener {
 
 fun loadNextPageClicked()
 
 }
  48. 48. Модуль mvp_list. Имплементация. Adapter. public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
 switch (viewType) {
 case BasePagingAdapter.TYPE_ITEM: {
 return new ItemViewHolder(getInflater().inflate(R.layout.list_item, parent, false));
 }
 case BasePagingAdapter.TYPE_LOAD_MANUALLY: {
 return new LoadFailedViewHolder(getInflater() .inflate(R.layout.list_item_load_failed, parent, false));
 }
 case BasePagingAdapter.TYPE_LOADER: {
 return new RecyclerView.ViewHolder(getInflater() .inflate(R.layout.list_item_loader, parent, false)) { };
 }
 default: {
 throw new IllegalArgumentException("Unsupported view type " + viewType);
 }
 }
 }
  49. 49. Модуль mvp_list. Имплементация. View. @Wrap public interface IPagingView extends IPagingSearchableView<AwesomeEntity, PagingResponse<AwesomeEntity>>, PagingPresenter.IPresenterView, PagingViewState.IViewStateView, PagingAdapter.PagingAdapterListener {
 
 }
  50. 50. Модуль mvp_list. Имплементация. Delegate. public class PagingDelegate
 extends BasePagingSearchableDelegate<AwesomeEntity, PagingResponse<AwesomeEntity>,
 IPagingView,
 PagingPresenter,
 PagingViewState>
 implements IPagingView
  51. 51. Модуль mvp_list. Имплементация. Delegate. protected void loadFirstPage()
 
 protected void loadNextPage()
 
 public PagingAdapter createPagingAdapter(LayoutInflater inflater, List<AwesomeEntity> items) public String getEmptyMessage(boolean isSearch) public String getErrorMessage(boolean isSearch, int code)
 

  52. 52. Модуль mvp_list. Имплементация. Delegate. var searchView: SearchView? = null var swipeRefreshLayout: SwipeRefreshLayout? = null var recyclerView: RecyclerView? = null var waitView: View? = null open fun setErrorView(vError: View, tvErrorMessage: TextView, retryButton: View?) open fun setEmptyView(vEmpty: View, tvEmptyMessage: TextView)
  53. 53. Модуль mvp_list. Имплементация. Fragment. @Layout(R.layout.view_paging_list)
 public class PagingFragment
 extends BaseMvpListFragment<AwesomeEntity, PagingResponse<AwesomeEntity>, PagingDelegate, IPagingView, PagingPresenter, PagingViewState> {
  54. 54. Модуль mvp_list. Имплементация. Fragment. private IPagingViewWrap delegateWrap = new IPagingViewWrap(getPagingDelegate());
 
 public IPagingView getMvpView() {
 return delegateWrap;
 }
 
 public PagingDelegate createDelegate() {
 return new PagingDelegate();
 }
  55. 55. Модуль mvp_list. Имплементация. Fragment. public PagingPresenter createListPresenter() {
 return new PagingPresenter();
 }
 
 public PagingViewState createListViewState() {
 return new PagingViewState();
 }
  56. 56. Модуль mvp_list. Имплементация. Fragment. @Override
 public void setupViewsToDelegate(@NotNull View view, @NonNull PagingDelegate delegate) {
 delegate.setSwipeRefreshLayout(view.findViewById(R.id.swipeToRefresh));
 delegate.setRecyclerView(view.findViewById(R.id.recycler));
 delegate.setWaitView(view.findViewById(R.id.waitView));
 }
  57. 57. Questions and Answers https://github.com/Ufkoku

×