SlideShare una empresa de Scribd logo
1 de 58
Descargar para leer sin conexión
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

Más contenido relacionado

La actualidad más candente

«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY
«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY
«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYYMail.ru Group
 
Веселая ферма. Соседи.
Веселая ферма. Соседи.Веселая ферма. Соседи.
Веселая ферма. Соседи.Doomer Samoiloff
 
C# Web. Занятие 11.
C# Web. Занятие 11.C# Web. Занятие 11.
C# Web. Занятие 11.Igor Shkulipa
 
Fun with core graphics
Fun with core graphicsFun with core graphics
Fun with core graphicsSoftTechnics
 
Fragments (Lecture 09 – Fragments)
Fragments (Lecture 09 – Fragments)Fragments (Lecture 09 – Fragments)
Fragments (Lecture 09 – Fragments)Noveo
 
Лекция Android. Fragments, ActionBar, Drawer
Лекция Android. Fragments, ActionBar, DrawerЛекция Android. Fragments, ActionBar, Drawer
Лекция Android. Fragments, ActionBar, DrawerАлександр Брич
 
UAFPUG6 - PureMVC
UAFPUG6 - PureMVCUAFPUG6 - PureMVC
UAFPUG6 - PureMVCmandrew182
 
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha DmitryUafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha DmitryMax Rozdobudko
 
FPUG Dzyga presentation
FPUG Dzyga presentationFPUG Dzyga presentation
FPUG Dzyga presentationIvan Filimonov
 
Где кончается react native? / Павел Кондратенко (Rambler&Co)
Где кончается react native? / Павел Кондратенко (Rambler&Co)Где кончается react native? / Павел Кондратенко (Rambler&Co)
Где кончается react native? / Павел Кондратенко (Rambler&Co)Ontico
 
Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularizationIvan Krylov
 
Android - 11 - Multithreading
Android - 11 - MultithreadingAndroid - 11 - Multithreading
Android - 11 - MultithreadingNoveo
 
Programming Guide
Programming GuideProgramming Guide
Programming Guideguest63e09c
 
платформа научных симуляторов Gpu digital lab
платформа научных симуляторов Gpu digital labплатформа научных симуляторов Gpu digital lab
платформа научных симуляторов Gpu digital labOleg Gubanov
 
2016-11-12 01 Егор Непомнящих. Агрегация и осведомленность
2016-11-12 01 Егор Непомнящих. Агрегация и осведомленность 2016-11-12 01 Егор Непомнящих. Агрегация и осведомленность
2016-11-12 01 Егор Непомнящих. Агрегация и осведомленность Омские ИТ-субботники
 

La actualidad más candente (18)

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

Similar a AndroidMVPHelper

Viper - чистая архитектура iOS-приложения (И. Чирков)
Viper - чистая архитектура iOS-приложения (И. Чирков)Viper - чистая архитектура iOS-приложения (И. Чирков)
Viper - чистая архитектура iOS-приложения (И. Чирков)65apps
 
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, ControllersШкола-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, ControllersГлеб Тарасов
 
Антон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в androidАнтон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в androidDataArt
 
Объять необъятное, или как использовать несколько MVVM фреймворков в одном XA...
Объять необъятное, или как использовать несколько MVVM фреймворков в одном XA...Объять необъятное, или как использовать несколько MVVM фреймворков в одном XA...
Объять необъятное, или как использовать несколько MVVM фреймворков в одном XA...Denis Tsvettsih
 
Rambler.iOS #5: VIPER и Swift
Rambler.iOS #5: VIPER и SwiftRambler.iOS #5: VIPER и Swift
Rambler.iOS #5: VIPER и SwiftRAMBLER&Co
 
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOSКурсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOSГлеб Тарасов
 
MVVM в WinForms – DevExpress Way (теория и практика)
MVVM в WinForms – DevExpress Way (теория и практика)MVVM в WinForms – DevExpress Way (теория и практика)
MVVM в WinForms – DevExpress Way (теория и практика)GoSharp
 
C# Desktop. Занятие 16.
C# Desktop. Занятие 16.C# Desktop. Занятие 16.
C# Desktop. Занятие 16.Igor Shkulipa
 
Как навести порядок в коде вашего web-приложения, Андрей Чебукин
Как навести порядок в коде вашего web-приложения, Андрей Чебукин Как навести порядок в коде вашего web-приложения, Андрей Чебукин
Как навести порядок в коде вашего web-приложения, Андрей Чебукин Sigma Software
 
Разработка WPF приложений в стиле ViewModel First
Разработка WPF приложений в стиле ViewModel FirstРазработка WPF приложений в стиле ViewModel First
Разработка WPF приложений в стиле ViewModel FirstDenis Tsvettsih
 
iOS and Android Mobile Test Automation
iOS and Android Mobile Test AutomationiOS and Android Mobile Test Automation
iOS and Android Mobile Test AutomationAndrii Dzynia
 
Принципы разработки ПО для iPhone с использованием акселерометра
Принципы разработки ПО для iPhone с использованием акселерометраПринципы разработки ПО для iPhone с использованием акселерометра
Принципы разработки ПО для iPhone с использованием акселерометраYandex
 
Mobile automation uamobile
Mobile automation uamobileMobile automation uamobile
Mobile automation uamobileUA Mobile
 
Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)
Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)
Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)Ontico
 
Превышаем скоростные лимиты с Angular 2
Превышаем скоростные лимиты с Angular 2Превышаем скоростные лимиты с Angular 2
Превышаем скоростные лимиты с Angular 2Oleksii Okhrymenko
 
#MBLTdev: Опыт использования MVVM в реальных проектах
#MBLTdev: Опыт использования MVVM в реальных проектах#MBLTdev: Опыт использования MVVM в реальных проектах
#MBLTdev: Опыт использования MVVM в реальных проектахe-Legion
 
Инструментируй это
Инструментируй этоИнструментируй это
Инструментируй этоRoman Dvornov
 

Similar a AndroidMVPHelper (20)

Viper - чистая архитектура iOS-приложения (И. Чирков)
Viper - чистая архитектура iOS-приложения (И. Чирков)Viper - чистая архитектура iOS-приложения (И. Чирков)
Viper - чистая архитектура iOS-приложения (И. Чирков)
 
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, ControllersШкола-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
 
Антон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в androidАнтон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в android
 
Async
AsyncAsync
Async
 
Объять необъятное, или как использовать несколько MVVM фреймворков в одном XA...
Объять необъятное, или как использовать несколько MVVM фреймворков в одном XA...Объять необъятное, или как использовать несколько MVVM фреймворков в одном XA...
Объять необъятное, или как использовать несколько MVVM фреймворков в одном XA...
 
Rambler.iOS #5: VIPER и Swift
Rambler.iOS #5: VIPER и SwiftRambler.iOS #5: VIPER и Swift
Rambler.iOS #5: VIPER и Swift
 
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOSКурсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
 
MVVM в WinForms – DevExpress Way (теория и практика)
MVVM в WinForms – DevExpress Way (теория и практика)MVVM в WinForms – DevExpress Way (теория и практика)
MVVM в WinForms – DevExpress Way (теория и практика)
 
C# Desktop. Занятие 16.
C# Desktop. Занятие 16.C# Desktop. Занятие 16.
C# Desktop. Занятие 16.
 
Как навести порядок в коде вашего web-приложения, Андрей Чебукин
Как навести порядок в коде вашего web-приложения, Андрей Чебукин Как навести порядок в коде вашего web-приложения, Андрей Чебукин
Как навести порядок в коде вашего web-приложения, Андрей Чебукин
 
Aspect Oriented Approach
Aspect Oriented ApproachAspect Oriented Approach
Aspect Oriented Approach
 
Разработка WPF приложений в стиле ViewModel First
Разработка WPF приложений в стиле ViewModel FirstРазработка WPF приложений в стиле ViewModel First
Разработка WPF приложений в стиле ViewModel First
 
iOS and Android Mobile Test Automation
iOS and Android Mobile Test AutomationiOS and Android Mobile Test Automation
iOS and Android Mobile Test Automation
 
Принципы разработки ПО для iPhone с использованием акселерометра
Принципы разработки ПО для iPhone с использованием акселерометраПринципы разработки ПО для iPhone с использованием акселерометра
Принципы разработки ПО для iPhone с использованием акселерометра
 
Mobile automation uamobile
Mobile automation uamobileMobile automation uamobile
Mobile automation uamobile
 
MWWM
MWWMMWWM
MWWM
 
Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)
Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)
Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)
 
Превышаем скоростные лимиты с Angular 2
Превышаем скоростные лимиты с Angular 2Превышаем скоростные лимиты с Angular 2
Превышаем скоростные лимиты с Angular 2
 
#MBLTdev: Опыт использования MVVM в реальных проектах
#MBLTdev: Опыт использования MVVM в реальных проектах#MBLTdev: Опыт использования MVVM в реальных проектах
#MBLTdev: Опыт использования MVVM в реальных проектах
 
Инструментируй это
Инструментируй этоИнструментируй это
Инструментируй это
 

Más de DataArt

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

Más de DataArt (20)

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

AndroidMVPHelper

  • 1.
  • 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));
 }