SlideShare a Scribd company logo
AndroidMVPHelper
AndroidMVPHelper
MVP на стероидах
Цели проекта
• Упростить интеграцию MVP паттерна;
• Избавиться от написания “рутинного” кода;
• Добавить дополнительный функционал.
Что такое MVP
View Presenter Model
● Представление (View) — реализует отображение данных, обращается к
представителю за обновлениями;
● Представитель (Presenter) — реализует взаимодействие между моделью
и представлением.
● Модель (Model) — содержит в себе бизнес-логику, получает данные из
хранилища.
Модули
base_mvp
mvp
mvp_presenter mvp_rx2_presenter
mvp_list
mvp_autosavable mvp_autosavable_annotation
mvp_view_wrap mvp_view_wrap_annotation
Модуль mvp
Основные классы:
• BaseMvpActivity
• BaseMvpFragment
• BaseMvpDialogFragment
Возможности:
• Управление жизненным циклом
компонентов
• Установка лейаута и инъекция вью-полей
• Зануление вью-полей
• LifeCycleObservable
Модуль mvp. 

Имплементация.
MVP component
IViewState IPresenter
Models
Модуль 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

}



}

Модуль 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.

}



}
Модуль mvp.
Имплементация. Presenter.
interface IPresenter<in T> {



fun onAttachView(view: T)



fun onDetachView()



}
Модуль mvp.
Имплементация. Presenter.
interface IAsyncPresenter<in T : IAsyncPresenter.ITaskListener> : IPresenter<T> {



fun cancel()



interface ITaskListener {



fun onTaskStatusChanged(taskId: Int, status: Int)



}



}

Модуль 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>
Модуль mvp.
Имплементация. Presenter.
fun waitForViewIfNeeded(): T
protected fun checkIfInterruptedException(ex: Throwable?): Boolean


protected fun isInMainThread(): Boolean
protected inline fun postOnMainThread(crossinline body: () -> Unit)
Модуль 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
Модуль 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
Модуль 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
Модуль 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
Модуль mvp.
Имплементация. View.
public interface IView extends Presenter.IPresenterView,
ViewState.IViewStateView {
//Other methods
}
Модуль 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)
}
Модуль 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)
}
Модуль mvp. 

Сохранение компонентов.
public class Fragment extends BaseMvpFragment<IView, Presenter, ViewState> implements IView {
@Override

public boolean retainPresenter() {

return true;

}



@Override

public boolean retainViewState() {

return true;

}
}
Модуль 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;

}



}
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.
Подписка на жизненный цикл.
Модуль mvp.
Подписка на жизненный цикл. Activity.
object ActivityLifecycle {
//Constants for supported activity lifecycle events
@Target(AnnotationTarget.FUNCTION)

@Retention(AnnotationRetention.RUNTIME)

@Inherited

annotation class OnLifecycleEvent(@ActivityEvent val event: Int)
}
Модуль mvp.
Подписка на жизненный цикл. Fragment.
object FragmentLifecycle {
//Constants for supported fragment lifecycle events
@Target(AnnotationTarget.FUNCTION)

@Retention(AnnotationRetention.RUNTIME)

@Inherited

annotation class OnLifecycleEvent(@FragmentEvent val event: Int)
}
Модуль 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)



}

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



public Fragment() {

cameraManager = new CameraManager();

subscribe(cameraManager);

}
}


Модуль mvp_autosavable.
Назначение:
• Сохранение полей ViewState в Bundle и
восстановление их оттуда.
Модуль 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;

}

Модуль mvp_autosavable.
Использование.
@Override

public void save(@NotNull Bundle bundle) {

ViewStateSaver.save(this, bundle);

}



@Override

public void restore(@NotNull Bundle bundle) {

ViewStateSaver.restore(this, bundle);

}
}
Модуль 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"));

}


}
Модуль mvp_view_wrap.
Назначение:
• Упрощает вызов методов в главном потоке из рабочих
потоков;
• Позволяет вызывать методы в главном потоке,
синхронно с работающим.
Модуль mvp_view_wrap.
Использование.
@Wrap

public interface IView extends Presenter.IPresenterView,
ViewState.IViewStateView {



void foo();



Object bar();



@Ignore

void ignoredMethod();



}
Модуль 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;

}
Модуль 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);

}

}
Модуль 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];
Модуль mvp_autosavable.
Сгенерированный класс. ignoredMethod()
public void ignoredMethod() {

wrappedView.ignoredMethod();

}
Модуль 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;

}
Модуль mvp_list.
Быстрая имплементация экранов со списком на основе
RecyclerView c
• Пейджингом
• Поиском
• Swipe to refresh
• Прогресс бары в списке и на весь экран
• Заглушки «нет контента» и «произошла ошибка»
Модуль mvp_list.
MVP component
IViewState IPresenter
Models
Delegate
Модуль mvp_list.
Имплементация. IPagingResponse.
interface IPagingResponse<I> {



val data: MutableList<I>



val canLoadMore: Boolean



}
Модуль 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>



}
Модуль 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
Модуль 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)



}
Модуль mvp_list.
Имплементация. Presenter.
public class PagingPresenter
extends BaseAsyncRxSchedulerPresenter<PagingPresenter.IPresenterView>
implements IPagingSearchablePresenter {
fun isFirstPageLoading(): Boolean



fun isNextPageLoading(): Boolean



fun cancelFirstPages()



fun cancelNextPages()



fun cancelAllPageRequests()
Модуль 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)


}
Модуль 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 {



}



}

Модуль mvp_list.
Имплементация. Adapter.
interface AdapterListener {



fun loadNextPageClicked()



}
Модуль 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);

}

}

}
Модуль mvp_list.
Имплементация. View.
@Wrap
public interface IPagingView
extends IPagingSearchableView<AwesomeEntity, PagingResponse<AwesomeEntity>>,
PagingPresenter.IPresenterView,
PagingViewState.IViewStateView,
PagingAdapter.PagingAdapterListener {



}
Модуль mvp_list.
Имплементация. Delegate.
public class PagingDelegate

extends BasePagingSearchableDelegate<AwesomeEntity,
PagingResponse<AwesomeEntity>,

IPagingView,

PagingPresenter,

PagingViewState>

implements IPagingView
Модуль 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)



Модуль 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)
Модуль mvp_list.
Имплементация. Fragment.
@Layout(R.layout.view_paging_list)

public class PagingFragment

extends BaseMvpListFragment<AwesomeEntity,
PagingResponse<AwesomeEntity>,
PagingDelegate,
IPagingView,
PagingPresenter,
PagingViewState> {
Модуль mvp_list.
Имплементация. Fragment.
private IPagingViewWrap delegateWrap = new IPagingViewWrap(getPagingDelegate());



public IPagingView getMvpView() {

return delegateWrap;

}



public PagingDelegate createDelegate() {

return new PagingDelegate();

}
Модуль mvp_list.
Имплементация. Fragment.
public PagingPresenter createListPresenter() {

return new PagingPresenter();

}



public PagingViewState createListViewState() {

return new PagingViewState();

}
Модуль 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));

}
Questions and Answers
https://github.com/Ufkoku

More Related Content

PPTX
MVP, Moxy. Как правильно пользоваться
PPT
Moxy – реализация MVP под Android. С щепоткой магии
PPTX
Luxoft async.net
PPTX
Moxy. Как правильно пользоваться? / Юрий Шмаков (Arello Mobile)
PPT
Moxy. Из чего состоит и как этим пользоваться
PDF
Школа-Студия разработки приложений для iOS. 5 лекция. Разное
PDF
Что нового в Android O (Grodno HTP)
PDF
Toolbar (Lecture 16 – toolbar)
MVP, Moxy. Как правильно пользоваться
Moxy – реализация MVP под Android. С щепоткой магии
Luxoft async.net
Moxy. Как правильно пользоваться? / Юрий Шмаков (Arello Mobile)
Moxy. Из чего состоит и как этим пользоваться
Школа-Студия разработки приложений для iOS. 5 лекция. Разное
Что нового в Android O (Grodno HTP)
Toolbar (Lecture 16 – toolbar)

What's hot (18)

PDF
«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY
PPSX
Веселая ферма. Соседи.
PDF
C# Web. Занятие 11.
PDF
Fun with core graphics
PDF
Лекция 2. Activity.
PDF
Fragments (Lecture 09 – Fragments)
PDF
Лекция Android. Fragments, ActionBar, Drawer
PPT
UAFPUG6 - PureMVC
PPT
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
PPT
PureMVC and Papervision
PDF
FPUG Dzyga presentation
PPT
Где кончается react native? / Павел Кондратенко (Rambler&Co)
PDF
Java 9: what is there beyond modularization
PDF
Fragments, ActionBar, Drawer
PDF
Android - 11 - Multithreading
PDF
Programming Guide
PPTX
платформа научных симуляторов Gpu digital lab
PDF
2016-11-12 01 Егор Непомнящих. Агрегация и осведомленность
«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY
Веселая ферма. Соседи.
C# Web. Занятие 11.
Fun with core graphics
Лекция 2. Activity.
Fragments (Lecture 09 – Fragments)
Лекция Android. Fragments, ActionBar, Drawer
UAFPUG6 - PureMVC
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
PureMVC and Papervision
FPUG Dzyga presentation
Где кончается react native? / Павел Кондратенко (Rambler&Co)
Java 9: what is there beyond modularization
Fragments, ActionBar, Drawer
Android - 11 - Multithreading
Programming Guide
платформа научных симуляторов Gpu digital lab
2016-11-12 01 Егор Непомнящих. Агрегация и осведомленность
Ad

More from DataArt (20)

PDF
DataArt Custom Software Engineering with a Human Approach
PDF
DataArt Healthcare & Life Sciences
PDF
DataArt Financial Services and Capital Markets
PDF
About DataArt HR Partners
PDF
Event management в IT
PDF
Digital Marketing from inside
PPTX
What's new in Android, Igor Malytsky ( Google Post I|O Tour)
PDF
DevOps Workshop:Что бывает, когда DevOps приходит на проект
PDF
IT Talk Kharkiv: «‎Soft skills в IT. Польза или вред? Максим Бастион, DataArt
PDF
«Ноль копеек. Спастись от выгорания» — Сергей Чеботарев (Head of Design, Han...
PDF
Communication in QA's life
PDF
Нельзя просто так взять и договориться, или как мы работали со сложными людьми
PDF
Знакомьтесь, DevOps
PDF
DevOps in real life
PDF
Codeless: автоматизация тестирования
PDF
Selenoid
PDF
Selenide
PDF
A. Sirota "Building an Automation Solution based on Appium"
PDF
Эмоциональный интеллект или как не сойти с ума в условиях сложного и динамичн...
PPTX
IT talk: Как я перестал бояться и полюбил TestNG
DataArt Custom Software Engineering with a Human Approach
DataArt Healthcare & Life Sciences
DataArt Financial Services and Capital Markets
About DataArt HR Partners
Event management в IT
Digital Marketing from inside
What's new in Android, Igor Malytsky ( Google Post I|O Tour)
DevOps Workshop:Что бывает, когда DevOps приходит на проект
IT Talk Kharkiv: «‎Soft skills в IT. Польза или вред? Максим Бастион, DataArt
«Ноль копеек. Спастись от выгорания» — Сергей Чеботарев (Head of Design, Han...
Communication in QA's life
Нельзя просто так взять и договориться, или как мы работали со сложными людьми
Знакомьтесь, DevOps
DevOps in real life
Codeless: автоматизация тестирования
Selenoid
Selenide
A. Sirota "Building an Automation Solution based on Appium"
Эмоциональный интеллект или как не сойти с ума в условиях сложного и динамичн...
IT talk: Как я перестал бояться и полюбил TestNG
Ad

AndroidMVPHelper

  • 3. Цели проекта • Упростить интеграцию MVP паттерна; • Избавиться от написания “рутинного” кода; • Добавить дополнительный функционал.
  • 4. Что такое MVP View Presenter Model ● Представление (View) — реализует отображение данных, обращается к представителю за обновлениями; ● Представитель (Presenter) — реализует взаимодействие между моделью и представлением. ● Модель (Model) — содержит в себе бизнес-логику, получает данные из хранилища.
  • 6. Модуль mvp Основные классы: • BaseMvpActivity • BaseMvpFragment • BaseMvpDialogFragment Возможности: • Управление жизненным циклом компонентов • Установка лейаута и инъекция вью-полей • Зануление вью-полей • LifeCycleObservable
  • 7. Модуль mvp. 
 Имплементация. MVP component IViewState IPresenter Models
  • 8. Модуль 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
 }
 
 }

  • 9. Модуль 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.
 }
 
 }
  • 10. Модуль mvp. Имплементация. Presenter. interface IPresenter<in T> {
 
 fun onAttachView(view: T)
 
 fun onDetachView()
 
 }
  • 11. Модуль mvp. Имплементация. Presenter. interface IAsyncPresenter<in T : IAsyncPresenter.ITaskListener> : IPresenter<T> {
 
 fun cancel()
 
 interface ITaskListener {
 
 fun onTaskStatusChanged(taskId: Int, status: Int)
 
 }
 
 }

  • 12. Модуль 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>
  • 13. Модуль mvp. Имплементация. Presenter. fun waitForViewIfNeeded(): T protected fun checkIfInterruptedException(ex: Throwable?): Boolean 
 protected fun isInMainThread(): Boolean protected inline fun postOnMainThread(crossinline body: () -> Unit)
  • 14. Модуль 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
  • 15. Модуль 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
  • 16. Модуль 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
  • 17. Модуль 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
  • 18. Модуль mvp. Имплементация. View. public interface IView extends Presenter.IPresenterView, ViewState.IViewStateView { //Other methods }
  • 19. Модуль 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) }
  • 20. Модуль 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) }
  • 21. Модуль mvp. 
 Сохранение компонентов. public class Fragment extends BaseMvpFragment<IView, Presenter, ViewState> implements IView { @Override
 public boolean retainPresenter() {
 return true;
 }
 
 @Override
 public boolean retainViewState() {
 return true;
 } }
  • 22. Модуль 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;
 }
 
 }
  • 23. 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. Подписка на жизненный цикл.
  • 24. Модуль mvp. Подписка на жизненный цикл. Activity. object ActivityLifecycle { //Constants for supported activity lifecycle events @Target(AnnotationTarget.FUNCTION)
 @Retention(AnnotationRetention.RUNTIME)
 @Inherited
 annotation class OnLifecycleEvent(@ActivityEvent val event: Int) }
  • 25. Модуль mvp. Подписка на жизненный цикл. Fragment. object FragmentLifecycle { //Constants for supported fragment lifecycle events @Target(AnnotationTarget.FUNCTION)
 @Retention(AnnotationRetention.RUNTIME)
 @Inherited
 annotation class OnLifecycleEvent(@FragmentEvent val event: Int) }
  • 26. Модуль 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)
 
 }

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

  • 28. Модуль mvp_autosavable. Назначение: • Сохранение полей ViewState в Bundle и восстановление их оттуда.
  • 29. Модуль 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;
 }

  • 30. Модуль mvp_autosavable. Использование. @Override
 public void save(@NotNull Bundle bundle) {
 ViewStateSaver.save(this, bundle);
 }
 
 @Override
 public void restore(@NotNull Bundle bundle) {
 ViewStateSaver.restore(this, bundle);
 } }
  • 31. Модуль 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"));
 } 
 }
  • 32. Модуль mvp_view_wrap. Назначение: • Упрощает вызов методов в главном потоке из рабочих потоков; • Позволяет вызывать методы в главном потоке, синхронно с работающим.
  • 33. Модуль mvp_view_wrap. Использование. @Wrap
 public interface IView extends Presenter.IPresenterView, ViewState.IViewStateView {
 
 void foo();
 
 Object bar();
 
 @Ignore
 void ignoredMethod();
 
 }
  • 34. Модуль 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;
 }
  • 35. Модуль 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);
 }
 }
  • 36. Модуль 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];
  • 37. Модуль mvp_autosavable. Сгенерированный класс. ignoredMethod() public void ignoredMethod() {
 wrappedView.ignoredMethod();
 }
  • 38. Модуль 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;
 }
  • 39. Модуль mvp_list. Быстрая имплементация экранов со списком на основе RecyclerView c • Пейджингом • Поиском • Swipe to refresh • Прогресс бары в списке и на весь экран • Заглушки «нет контента» и «произошла ошибка»
  • 41. Модуль mvp_list. Имплементация. IPagingResponse. interface IPagingResponse<I> {
 
 val data: MutableList<I>
 
 val canLoadMore: Boolean
 
 }
  • 42. Модуль 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>
 
 }
  • 43. Модуль 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
  • 44. Модуль 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)
 
 }
  • 45. Модуль mvp_list. Имплементация. Presenter. public class PagingPresenter extends BaseAsyncRxSchedulerPresenter<PagingPresenter.IPresenterView> implements IPagingSearchablePresenter { fun isFirstPageLoading(): Boolean
 
 fun isNextPageLoading(): Boolean
 
 fun cancelFirstPages()
 
 fun cancelNextPages()
 
 fun cancelAllPageRequests()
  • 46. Модуль 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) 
 }
  • 47. Модуль 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 {
 
 }
 
 }

  • 48. Модуль mvp_list. Имплементация. Adapter. interface AdapterListener {
 
 fun loadNextPageClicked()
 
 }
  • 49. Модуль 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);
 }
 }
 }
  • 50. Модуль mvp_list. Имплементация. View. @Wrap public interface IPagingView extends IPagingSearchableView<AwesomeEntity, PagingResponse<AwesomeEntity>>, PagingPresenter.IPresenterView, PagingViewState.IViewStateView, PagingAdapter.PagingAdapterListener {
 
 }
  • 51. Модуль mvp_list. Имплементация. Delegate. public class PagingDelegate
 extends BasePagingSearchableDelegate<AwesomeEntity, PagingResponse<AwesomeEntity>,
 IPagingView,
 PagingPresenter,
 PagingViewState>
 implements IPagingView
  • 52. Модуль 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)
 

  • 53. Модуль 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)
  • 54. Модуль mvp_list. Имплементация. Fragment. @Layout(R.layout.view_paging_list)
 public class PagingFragment
 extends BaseMvpListFragment<AwesomeEntity, PagingResponse<AwesomeEntity>, PagingDelegate, IPagingView, PagingPresenter, PagingViewState> {
  • 55. Модуль mvp_list. Имплементация. Fragment. private IPagingViewWrap delegateWrap = new IPagingViewWrap(getPagingDelegate());
 
 public IPagingView getMvpView() {
 return delegateWrap;
 }
 
 public PagingDelegate createDelegate() {
 return new PagingDelegate();
 }
  • 56. Модуль mvp_list. Имплементация. Fragment. public PagingPresenter createListPresenter() {
 return new PagingPresenter();
 }
 
 public PagingViewState createListViewState() {
 return new PagingViewState();
 }
  • 57. Модуль 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));
 }