рдореИрдВ рдХреБрдЫ рд╕рд╛рд▓ рдкрд╣рд▓реЗ рдЯрд┐рдВрдХрдлреЙрдлрд╝ рдореЗрдВ рдЖрдпрд╛ рдерд╛, рдПрдХ рдирдП рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХрд╕реНрдЯрдорд░реНрд╕ рдПрдВрдб рдкреНрд░реЛрдЬреЗрдХреНрдЯреНрд╕ рдкрд░ , рдЬреЛ рддрдм рд╢реБрд░реВ рд╣реЛ рд░рд╣рд╛ рдерд╛ред
рдЕрдм рдореБрдЭреЗ рдореЗрд░реЗ рд▓рд┐рдП рддрддреНрдХрд╛рд▓реАрди рдирдИ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рд╕реЗ рдЕрдкрдиреА рднрд╛рд╡рдирд╛рдУрдВ рдХреЛ рдпрд╛рдж рдирд╣реАрдВ рд╣реИред рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрдХреАрди рд╣реИ рдХрд┐ рдпрд╛рдж рд╣реИ: рдпрд╣ рдЕрд╕рд╛рдорд╛рдиреНрдп рдерд╛ рдХрд┐ рдЖрд░рдПрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд╣реАрдВ рдФрд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдиреЗрдЯрд╡рд░реНрдХ рдХреА рд╕рд╛рдорд╛рдиреНрдп рдпрд╛рддреНрд░рд╛рдУрдВ рдХреЗ рдмрд╛рд╣рд░ рдФрд░ рдЖрдзрд╛рд░ рддрдХред рдЕрдм рдЬрдм рдпрд╣ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╡рд┐рдХрд╛рд╕ рдХреЗ рдХреБрдЫ рд╡рд┐рдХрд╛рд╕рд╡рд╛рджреА рдорд╛рд░реНрдЧ рд╕реЗ рдЧреБрдЬрд░ рдЪреБрдХрд╛ рд╣реИ, рдореИрдВ рдЕрдВрдд рдореЗрдВ рдмрд╛рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдХреНрдпрд╛ рд╣реБрдЖ рдФрд░ рдХреНрдпрд╛ рд╣реБрдЖред

рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, рд╕рднреА рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд▓реЛрдХрдкреНрд░рд┐рдп рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ - рдПрдорд╡реАрдкреА, рдПрдорд╡реАрд╡реАрдПрдо рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдПрдорд╡реАрдЖрдИ - рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рдЕрдЦрд╛рдбрд╝реЗ рдореЗрдВ рд╣реИрдВ рдФрд░ рд╣рдореЗрд╢рд╛ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд▓рд╛рдпрдХ рдирд╣реАрдВ рд╣реИрдВред рдХреНрдпрд╛ рдЙрдирдореЗрдВ рдЦрд╛рдорд┐рдпрд╛рдВ рдирд╣реАрдВ рд╣реИрдВ? рдореИрдВ рдЙрдирдореЗрдВ рд╕реЗ рдмрд╣реБрдд рдХреБрдЫ рджреЗрдЦрддрд╛ рд╣реВрдВред рд╣рдордиреЗ рдЕрдкрдиреЗ рд╕реНрдерд╛рди рдкрд░ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ рдХрд┐ рдЗрд╕реЗ рд╕рд╣рдирд╛ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ, рдФрд░ (рдкреБрдирдГ) рдПрдХ рдирдИ, рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХрд╛ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рдХрд┐рдпрд╛ред
рдореИрдВ рд╡рд░реНрддрдорд╛рди рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬреЛ рдХреБрдЫ рдореБрдЭреЗ рдкрд╕рдВрдж рдирд╣реАрдВ рд╣реИ рдЙрд╕рдХрд╛ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рд╡рд░реНрдгрди рдХрд░реВрдВрдЧрд╛ред рдХреБрдЫ рдмрд┐рдВрджреБ рд╡рд┐рд╡рд╛рджрд╛рд╕реНрдкрдж рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рд╢рд╛рдпрдж рдЖрдкрдиреЗ рдХрднреА рдЗрд╕рдХрд╛ рд╕рд╛рдордирд╛ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ, рдЖрдк рд╕рд╣реА рдФрд░ рдЖрдо рддреМрд░ рдкрд░ рдЬреЗрдбреА рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рд▓рд┐рдЦрддреЗ рд╣реИрдВред рдлрд┐рд░ рдореБрдЭреЗ рдХреНрд╖рдорд╛ рдХрд░реЛ, рдкрд╛рдкреАред
рддреЛ рдореЗрд░рд╛ рджрд░реНрдж рд╣реИ:
- рд╡рд┐рд╢рд╛рд▓ рдкреНрд░рд╕реНрддреБрддрдХрд░реНрддрд╛ / ViewModelред
- MVI рдореЗрдВ рд╕реНрд╡рд┐рдЪ-рдХреЗрд╕ рдХреА рдПрдХ рдмрдбрд╝реА рд░рд╛рд╢рд┐ред
- рдкреНрд░рд╕реНрддреБрддрдХрд░реНрддрд╛ / ViewModel рдХреЗ рднрд╛рдЧреЛрдВ рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рдЕрд╕рдорд░реНрдерддрд╛ рдФрд░, рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреЛрдб рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
- рдкрд░рд┐рд╡рд░реНрддрдирд╢реАрд▓ рдЪрд░реЛрдВ рдХреЗ рдвреЗрд░ рдЬрд┐рдиреНрд╣реЗрдВ рдХрд╣реАрдВ рд╕реЗ рднреА рд╕рдВрд╢реЛрдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рддрджрдиреБрд╕рд╛рд░, рдРрд╕реЗ рдХреЛрдб рдХреЛ рдмрдирд╛рдП рд░рдЦрдирд╛ рдФрд░ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИред
- рд╡рд┐рдШрдЯрд┐рдд рд╕реНрдХреНрд░реАрди рдЕрдкрдбреЗрдЯ рдирд╣реАрдВред
- рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ рдХрдард┐рди рд╣реИред
рд╕рдорд╕реНрдпрд╛рдУрдВ
рд╕рдордп рдкрд░ рд╣рд░ рдХреНрд╖рдг, рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕реНрдерд┐рддрд┐ рд╣реЛрддреА рд╣реИ рдЬреЛ рдЙрд╕рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреА рд╣реИ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЬреЛ рджреЗрдЦрддрд╛ рд╣реИред рдЗрд╕ рд░рд╛рдЬреНрдп рдореЗрдВ рдЪрд░ рдХреЗ рд╕рднреА рдореВрд▓реНрдп рд╢рд╛рдорд┐рд▓ рд╣реИрдВ - рд╕рд╛рдзрд╛рд░рдг рдЭрдВрдбреЗ рд╕реЗ рд▓реЗрдХрд░ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд╡рд╕реНрддреБрдУрдВ рддрдХред рдЗрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдЪрд░ рдЕрдкрдиреА рдЦреБрдж рдХреА рдЬрд┐рдВрджрдЧреА рдЬреАрддрд╛ рд╣реИ рдФрд░ рдХреЛрдб рдХреЗ рд╡рд┐рднрд┐рдиреНрди рд╣рд┐рд╕реНрд╕реЛрдВ рджреНрд╡рд╛рд░рд╛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЖрдк рдХреЗрд╡рд▓ рдПрдХ рдХреЗ рдмрд╛рдж рдПрдХ рдЙрди рд╕рднреА рдХреА рдЬрд╛рдБрдЪ рдХрд░рдХреЗ рд╣реА рдЖрд╡реЗрджрди рдХреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЖрдзреБрдирд┐рдХ рдХреЛрдЯрд▓рд┐рди рдПрдорд╡реАрдЖрдИ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдкрд░ рдПрдХ рд▓реЗрдЦ
рдЕрдзреНрдпрд╛рдп 1. рд╡рд┐рдХрд╛рд╕ рд╣реА рд╣рдорд╛рд░рд╛ рд╕рдм рдХреБрдЫ рд╣реИ
рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ, рд╣рдордиреЗ рдПрдорд╡реАрдкреА рдкрд░ рд▓рд┐рдЦрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдереЛрдбрд╝рд╛ рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрд┐рддред рдпрд╣ рдПрдорд╡реАрдкреА рдФрд░ рдПрдорд╡реАрдЖрдИ рдХрд╛ рдорд┐рд╢реНрд░рдг рдерд╛ред рдкреНрд░рд╕реНрддреБрддрдХрд░реНрддрд╛ рдФрд░ рджреГрд╢реНрдп рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд░реВрдк рдореЗрдВ MVP рд╕реЗ рдирд┐рдХрд╛рдп рдереЗ:
interface NewTaskView { val newTaskAction: Observable<NewTaskAction> val taskNameChangeAction: Observable<String> val onChangeState: Consumer<SomeViewState> }
рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдпрд╣рд╛рдВ рдЖрдк рдкрдХрдбрд╝ рдХреЛ рдиреЛрдЯрд┐рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ: рдпрд╣рд╛рдВ рджреЗрдЦреЗрдВ рдПрдорд╡реАрдкреА рдХреЗ рдХреИрдирди рд╕реЗ рдмрд╣реБрдд рджреВрд░ рд╣реИред рдкреНрд░рд╕реНрддреБрддрдХрд░реНрддрд╛ рдореЗрдВ рдПрдХ рд╡рд┐рдзрд┐ рдереА:
fun bind(view: SomeView): Disposable
рдмрд╛рд╣рд░, рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдЬреЛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рддреНрдордХ рд░реВрдк рд╕реЗ рдпреВрдЖрдИ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреА рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрддрд╛ рд╣реИред рдФрд░ рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдорд╡реАрдЖрдИ рдХреА рд╕реНрдореИрдХ рд╣реИ!
рдЬреНрдпрд╛рджрд╛ рд╣реИред рдкреНрд░рд╕реНрддреБрддрдХрд░реНрддрд╛ рдореЗрдВ, рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЗрдВрдЯрд░реЗрдХреНрдЯрд░реНрд╕ рдмрдирд╛рдП рдЧрдП рдФрд░ рд╡реНрдпреВ рдореЗрдВ рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдм рдХрд┐рдпрд╛ рдЧрдпрд╛, рд▓реЗрдХрд┐рди рдЙрдиреНрд╣реЛрдВрдиреЗ UI рддрд░реАрдХреЛрдВ рдХреЛ рд╕реАрдзреЗ рдХреЙрд▓ рдирд╣реАрдВ рдХрд┐рдпрд╛, рд▓реЗрдХрд┐рди рдХреБрдЫ рд╡реИрд╢реНрд╡рд┐рдХ рд░рд╛рдЬреНрдп рд╡рд╛рдкрд╕ рдХрд░ рджрд┐рдП, рдЬрд┐рд╕рдореЗрдВ рд╕рднреА рд╕рдВрднрд╛рд╡рд┐рдд рд╕реНрдХреНрд░реАрди рд╕реНрдЯреЗрдЯреНрд╕ рдереЗ:
compositeDisposable.add( Observable.merge(firstAction, secondAction) .observeOn(AndroidSchedulers.mainThread()) .subscribe(view.onChangeState)) return compositeDisposable
class SomeViewState(val progress: Boolean? = null, val error: Throwable? = null, val errorMessage: String? = error?.message, val result: TaskUi? = null)
рдЧрддрд┐рд╡рд┐рдзрд┐ SomeViewStateMachine рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреА рд╡рдВрд╢рдЬ рдереА:
interface SomeViewStateMachine { fun toSuccess(task: SomeUiModel) fun toError(error: String?) fun toProgress() fun changeSomeButton(buttonEnabled: Boolean) }
рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реНрдХреНрд░реАрди рдкрд░ рдХрд┐рд╕реА рдЪреАрдЬрд╝ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдПрдХ рдШрдЯрдирд╛ рдкреНрд░рд╕реНрддреБрддрдХрд░реНрддрд╛ рдореЗрдВ рдЖрддреА рд╣реИ рдФрд░ рдЙрд╕рдиреЗ рдПрдХ рдирдпрд╛ рдореЙрдбрд▓ рдмрдирд╛рдпрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╡реЗрдмрд╕рд╛рдЗрдЯ рджреНрд╡рд╛рд░рд╛ рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
class SomeViewStateResolver(private val stateMachine: SomeViewStateMachine) : Consumer<SomeViewState> { override fun accept(stateUpdate: SomeViewState) { if (stateUpdate.result != null) { stateMachine.toSuccess(stateUpdate.result) } else if (stateUpdate.error != null && stateUpdate.progress == false) { stateMachine.toError(stateUpdate.errorMessage) } else if (stateUpdate.progress == true) { stateMachine.toProgress() } else if (stateUpdate.someButtonEnabled != null) { stateMachine.changeSomeButton(stateUpdate.someButtonEnabled) } } }
рд╕рд╣рдордд рд╣реВрдБ, рдХреБрдЫ рдЕрдЬреАрдм рдПрдорд╡реАрдкреА, рдФрд░ рдПрдорд╡реАрдЖрдИ рд╕реЗ рднреА рджреВрд░ред рдкреНрд░реЗрд░рдгрд╛ рдХреА рддрд▓рд╛рд╢ рдореЗрдВред
рдЕрдзреНрдпрд╛рдп 2. Redux

рдЕрдиреНрдп рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд╕рд╛рде рдЙрдирдХреА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рддреЗ рд╣реБрдП, рд╣рдорд╛рд░реЗ (рддрдм рднреА) рдиреЗрддрд╛ рд╕рд░реНрдЧреЗрдИ рдмреЛрдЗрд╢реНрдЯрди рдиреЗ рд░реЗрдбрдХреНрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реАрдЦрд╛ред
рд╕рднреА рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдбреЛрд░рдлрд╝рдореИрди рдХреА рдмрд╛рдд рджреЗрдЦрдиреЗ рдФрд░ Redux рдХреЗ рд╕рд╛рде рдЦреЗрд▓рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдордиреЗ рдЕрдкрдиреА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЛ рдЕрдкрдЧреНрд░реЗрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред
рд▓реЗрдХрд┐рди рдкрд╣рд▓реЗ, рдЪрд▓реЛ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ рдФрд░ рдЗрд╕рдХреЗ рдкреЗрд╢реЗрд╡рд░реЛрдВ рдФрд░ рд╡рд┐рдкрдХреНрд╖реЛрдВ рдХреЛ рджреЗрдЦреЗрдВред
рдХрд╛рд░реНрдп
рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИред
ActionCreator
рд╡рд╣ рдПрдХ рд╕рд┐рд╕реНрдЯрдо рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХреА рддрд░рд╣ рд╣реИ: рдкреНрд░рд╛рд░реВрдк, рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХрд╛ рдЕрдиреБрдкрд╛рд▓рди рдХрд░рддрд╛ рд╣реИ рддрд╛рдХрд┐ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдЙрд╕реЗ рд╕рдордЭ рд╕рдХреЗрдВред
рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реНрдХреНрд░реАрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддрд╛ рд╣реИ, рддреЛ ActionsCreator рдПрдХ рдПрдХреНрд╢рди рдмрдирд╛рддрд╛ рд╣реИ рдЬреЛ рдорд┐рдбрд▓рд╡реЗрдпрд░ (рдХреБрдЫ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ) рдкрд░ рдЬрд╛рддрд╛ рд╣реИред рд╡реНрдпрд╛рдкрд╛рд░ рддрд░реНрдХ рд╣рдореЗрдВ рдирдпрд╛ рдбреЗрдЯрд╛ рджреЗрддрд╛ рд╣реИ рдЬреЛ рдПрдХ рд╡рд┐рд╢реЗрд╖ Reducer рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред
рдпрджрд┐ рдЖрдк рддрд╕реНрд╡реАрд░ рдХреЛ рдлрд┐рд░ рд╕реЗ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдХрд┐рд╕реА рд╡рд╕реНрддреБ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╕реНрдЯреЛрд░ рд╕реНрдЯреЛрд░ Reducersред рдпрд╣реА рд╣реИ, рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рд╕рд╛рдордиреЗ рд╡рд╛рд▓реЗ рднрд╛рдЗрдпреЛрдВ - рджреБрд░реНрднрд╛рдЧреНрдпрдкреВрд░реНрдг рднрд╛рдЗрдпреЛрдВ - рдиреЗ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдпрд╛ рд╣реИ рдХрд┐ рдПрдХ рдмрдбрд╝реА рд╡рд╕реНрддреБ рдХреЛ рдХрдИ рдЫреЛрдЯреЗ рд▓реЛрдЧреЛрдВ рдореЗрдВ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рд╕реНрдХреНрд░реАрди рдХреЗ рдЕрдкрдиреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧрд╛ред рдФрд░ рдпрд╣ рд╕рд┐рд░реНрдл рдПрдХ рдЕрджреНрднреБрдд рд╡рд┐рдЪрд╛рд░ рд╣реИ!
рд╕рд░рд▓ ActionCreators (рд╕рд╛рд╡рдзрд╛рди, рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ!) рдХреЗ рд▓рд┐рдП рдирдореВрдирд╛ рдХреЛрдб:
export function addTodo(text) { return { type: ADD_TODO, text } } export function toggleTodo(index) { return { type: TOGGLE_TODO, index } } export function setVisibilityFilter(filter) { return { type: SET_VISIBILITY_FILTER, filter } }
рдХрдо рдХрд░рдиреЗ
рдХреНрд░рд┐рдпрд╛рдПрдВ рдЗрд╕ рддрдереНрдп рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреА рд╣реИрдВ рдХрд┐ рдХреБрдЫ рд╣реБрдЖ, рд▓реЗрдХрд┐рди рдпрд╣ рдЗрдВрдЧрд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЖрд╡реЗрджрди рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдХреИрд╕реЗ рдмрджрд▓рдирд╛ рдЪрд╛рд╣рд┐рдП, рдпрд╣ Reducer рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, Reducer рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рд╡рд┐рдШрдЯрд┐рдд / рд╕реНрдХреНрд░реАрди рдХреЛ рддрд╛рдЬрд╝рд╛ рдХреИрд╕реЗ рдХрд░реЗрдВред
рдкреЗрд╢реЗрд╡рд░реЛрдВ:
- рд╡рд┐рдШрдЯрд┐рдд рд╕реНрдХреНрд░реАрди рдЕрдкрдбреЗрдЯред
- рдЕрдкреНрд░рддреНрдпрдХреНрд╖ рдбреЗрдЯрд╛ рд╕реНрдЯреНрд░реАрдоред
рд╡рд┐рдкрдХреНрд╖:
- рдкрд╕рдВрджреАрджрд╛ рд╕реНрд╡рд┐рдЪ рдлрд┐рд░ рд╕реЗред
function todoApp(state = initialState, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return Object.assign({}, state, { visibilityFilter: action.filter }) case ADD_TODO: return Object.assign({}, state, { todos: [ ...state.todos, { text: action.text, completed: false } ] }) default: return state }
- рд░рд╛рдЬреНрдп рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ред
- ActionCreator рдФрд░ Reducer рдореЗрдВ рддрд░реНрдХ рдХрд╛ рдкреГрдердХреНрдХрд░рдгред
рд╣рд╛рдВ, рдпрд╣ рд╣рдореЗрдВ рд▓рдЧ рд░рд╣рд╛ рдерд╛ рдХрд┐ рдПрдХреНрд╢рди рдХреНрд░рд┐рдПрдЯрд░ рдФрд░ рд░реЗрдбреНрдпреВрд╕рд░ рдХрд╛ рдЕрд▓рдЧрд╛рд╡ рдореЙрдбрд▓ рдФрд░ рд╕реНрдХреНрд░реАрди рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдХрд▓реНрдк рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрдВрд╕реНрдЯрд╛рдлреЙрдлрд╝ (рд▓рд┐рдЦрдирд╛) рдПрдХ рдмреБрд░рд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣реИред рдФрд░ рдпрд╣рд╛рдБ рд╣рдордиреЗ рдЕрдкрдиреА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХрд╛ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рдХрд┐рдпрд╛!
рдЕрдзреНрдпрд╛рдп 3. рдИрдмреАрдП

рдИрдмреАрдП рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдПрдХреНрд╢рди рдФрд░ рдПрдХреНрд╢рди рдХреНрд░рд┐рдПрдЯрд░ рдХреНрдпрд╛ рд╣реИ:
typealias Action = () -> Unit typealias ActionMapper<T> = (T) -> Action interface ActionCreator<T> : (T) -> (Observable<Action>)
рд╣рд╛рдВ, рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХрд╛ рдЖрдзрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдЯрд╛рдЗрдкреЗрд▓рд┐рдпрд╛рд╕ рдФрд░ рдПрдХ рдЗрдВрдЯрд░рдлреЗрд╕ рд╣реИред рд╕рд╛рджрдЧреА рд▓рд╛рд▓рд┐рддреНрдп рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИ!
рдХрд┐рд╕реА рднреА рдбреЗрдЯрд╛ рдХреЛ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд┐рдП рдмрд┐рдирд╛ рдХреБрдЫ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ ActionCreator рдПрдХ рдСрдмреНрдЬрд░реНрд╡реЗрдмрд▓ рд░рд┐рдЯрд░реНрди рджреЗрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдХреБрдЫ рдбреЗрдЯрд╛ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХреНрд╢рди рдХреЛ рджреВрд╕рд░реЗ рд▓реИрдореНрдмреНрдбрд╛ рдореЗрдВ рд▓рдкреЗрдЯрдирд╛ рдкрдбрд╝рд╛ред рдФрд░ рдЗрд╕рд▓рд┐рдП рдЗрд╕рдиреЗ ActionMapper - рдПрдХ рдЯрд╛рдЗрдк рдПрдХреНрд╢рди рдХрд┐рдпрд╛, рдЬрд┐рд╕рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣рдо рд╕реНрдХреНрд░реАрди / рджреГрд╢реНрдп рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЙрд╕реЗ рдкрд╛рд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдореВрд▓ рдЖрд╕рди:
рдПрдХ ActionCreator - рд╕реНрдХреНрд░реАрди рдХрд╛ рдПрдХ рд╣рд┐рд╕реНрд╕рд╛рдкрд╣рд▓реЗ рдкреИрд░рд╛рдЧреНрд░рд╛рдл рдХреЗ рд╕рд╛рде, рд╕рдм рдХреБрдЫ рд╕реНрдкрд╖реНрдЯ рд╣реИ: рддрд╛рдХрд┐ рд╕рдордЭ рд╕реЗ рдмрд╛рд╣рд░ рдХреЗ рдХреНрд░реЙрд╕-рдЕрдкрдбреЗрдЯ рд╕реЗ рдХреЛрдИ рдирд░рдХ рди рд╣реЛ, рд╣рдо рдЗрд╕ рдмрд╛рдд рдкрд░ рд╕рд╣рдордд рд╣реБрдП рдХрд┐ рдПрдХ рдПрдХреНрд╢рди рдХреНрд░рд┐рдПрдЯрд░ рд╕реНрдХреНрд░реАрди рдХреЗ рдХреЗрд╡рд▓ рд╣рд┐рд╕реНрд╕реЗ рдХреЛ рд╣реА рдЕрдкрдбреЗрдЯ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдпрджрд┐ рдпрд╣ рдПрдХ рд╕реВрдЪреА рд╣реИ, рддреЛ рдпрд╣ рдХреЗрд╡рд▓ рд╕реВрдЪреА рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИ, рдЕрдЧрд░ рдмрдЯрди рдХреЗрд╡рд▓ рдЗрд╕реЗред
рдбреИрдЧрд░ рдХреА рдЬрд░реВрд░рдд рдирд╣реАрдВ рд╣реИрд▓реЗрдХрд┐рди, рдПрдХ рдЪрдорддреНрдХрд╛рд░, рдбреИрдЧрд░ рдиреЗ рд╣рдореЗрдВ рдЦреБрд╢ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд┐рдпрд╛? рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рддрд╛ рд╣реВрдВред
рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╣рд╛рдиреА рд╣реИ рдЬрдм рдПрдХ рд╕рд╛рд░ рд╕рд░реНрдЧреЗрдИ рдЙрд░реНрдл тАЛтАЛрдбреИрдЧрд░ рдорд╛рд╕реНрдЯрд░ рдЙрд░реНрдл тАЛтАЛ"рдпрд╣ рд╕рд╛рд░ рдХреНрдпрд╛ рдХрд░рддрд╛ рд╣реИ?" рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкрд░ рд╣реИред
рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдпрджрд┐ рдЖрдкрдиреЗ рдПрдХ рдЦрдВрдЬрд░ рдХреЗ рд╕рд╛рде рдкреНрд░рдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдкреНрд░рддреНрдпреЗрдХ рдирдП (рдФрд░ рди рдХреЗрд╡рд▓ рдирдП) рдбреЗрд╡рд▓рдкрд░ рдХреЛ рд╣рд░ рдмрд╛рд░ рд╕рдордЭрд╛рдирд╛ рд╣реЛрдЧрд╛ред рдпрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЦреБрдж рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рднреВрд▓ рдЧрдП рдХрд┐ рдпрд╣ рдПрдиреЛрдЯреЗрд╢рди рдХреНрдпрд╛ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЖрдк Google рдкрд░ рдЬрд╛рддреЗ рд╣реИрдВред
рдпрд╣ рд╕рдм рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛ рд╢реБрд░реВ рдХрд┐рдП рдмрд┐рдирд╛ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдмрд╣реБрдд рдЬрдЯрд┐рд▓ рдХрд░рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╣рдордиреЗ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рдХрд┐ рд╣рдо рдЕрдкрдиреЗ рд╣рд╛рдереЛрдВ рд╕реЗ рдЬрд╝рд░реВрд░рдд рдХреА рдЪреАрдЬреЗрдВ рдмрдирд╛рдПрдБрдЧреЗ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рдЗрдХрдЯреНрдард╛ рдХрд░рдирд╛ рддреЗрдЬреА рд╕реЗ рд╣реЛрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдХреЛрдИ рдХреЛрдб рдкреАрдврд╝реА рдирд╣реАрдВ рд╣реИред рд╣рд╛рдВ, рд╣рдо рдЕрдкрдиреЗ рд╣рд╛рдереЛрдВ рд╕реЗ рд╕рднреА рдирд┐рд░реНрднрд░рддрд╛рдУрдВ рдХреЛ рд▓рд┐рдЦрддреЗ рд╣реБрдП рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдкрд╛рдВрдЪ рдорд┐рдирдЯ рдмрд┐рддрд╛рдПрдВрдЧреЗ, рд▓реЗрдХрд┐рди рд╣рдо рд╕рдВрдХрд▓рди рдкрд░ рдмрд╣реБрдд рд╕рдордп рдмрдЪрд╛рдПрдВрдЧреЗред рд╣рд╛рдВ, рд╣рдордиреЗ рд╣рд░ рдЬрдЧрд╣ рдЦрдВрдЬрд░ рдХрд╛ рдкрд░рд┐рддреНрдпрд╛рдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ, рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡реИрд╢реНрд╡рд┐рдХ рд╕реНрддрд░ рдкрд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдпрд╣ рдХреБрдЫ рд╕рд╛рдорд╛рдиреНрдп рдЪреАрдЬреЗрдВ рдмрдирд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо рдЙрдиреНрд╣реЗрдВ рдЬрд╛рд╡рд╛ рдореЗрдВ рдмреЗрд╣рддрд░ рдЕрдиреБрдХреВрд▓рди рдХреЗ рд▓рд┐рдП рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рддрд╛рдХрд┐ рдХреЗрдкреНрдЯ рдХреЛ рдЖрдХрд░реНрд╖рд┐рдд рди рдХрд░реЗрдВред
рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдпреЛрдЬрдирд╛ :

рдШрдЯрдХ рдбреИрдЧрд░ рд╕реЗ рдПрдХ рд╣реА рдШрдЯрдХ рдХрд╛ рдПрдХ рдПрдирд╛рд▓реЙрдЧ рд╣реИ, рдХреЗрд╡рд▓ рдбреИрдЧрд░ рдХреЗ рдмрд┐рдирд╛ред рдЙрд╕рдХрд╛ рдХрд╛рдо рдмрд╛рдЗрдВрдбрд░ рдмрдирд╛рдирд╛ рд╣реИред рдмрд╛рдЗрдВрдбрд░ рдПрдХреНрд╢рдирдХреНрд░рд┐рдПрдЯрд░реНрд╕ рдХреЛ рдПрдХ рд╕рд╛рде рдЬреЛрдбрд╝ рджреЗрддрд╛ рд╣реИред рд╡реНрдпреВ рд╕реЗ рдмрд┐рдВрдбрд░ рдЗрд╡реЗрдВрдЯ рддрдХ рдХреНрдпрд╛ рд╣реБрдЖ, рдФрд░ рдмрд┐рдВрджрд░ рд╕реЗ рд╡реНрдпреВ рдХреЗ рд▓рд┐рдП, рдПрдХреНрд╢рди рднреЗрдЬреЗ рдЬрд╛рддреЗ рд╣реИрдВ рдЬреЛ рд╕реНрдХреНрд░реАрди рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддреЗ рд╣реИрдВред
ActionCreator

рдЕрдм рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдХрд┐рд╕ рддрд░рд╣ рдХреА рдЪреАрдЬ рд╣реИ - рдПрдХреНрд╢рдирдХреНрд░реЗрдЯрд░ред рд╕рд░рд▓рддрдо рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдХреЗрд╡рд▓ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рдЕрдкреНрд░рддреНрдпрдХреНрд╖ рд░реВрдк рд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИред рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдРрд╕рд╛ рдХреЛрдИ рдкрд░рд┐рджреГрд╢реНрдп рд╣реИ: рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдиреЗ "рдХрд╛рд░реНрдп рдмрдирд╛рдПрдВ" рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд┐рдпрд╛ред рдПрдХ рдФрд░ рд╕реНрдХреНрд░реАрди рдЦреБрд▓рдиреА рдЪрд╛рд╣рд┐рдП, рдЬрд╣рд╛рдВ рд╣рдо рдЗрд╕рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВрдЧреЗ, рдмрд┐рдирд╛ рдХрд┐рд╕реА рдЕрддрд┐рд░рд┐рдХреНрдд рдЕрдиреБрд░реЛрдз рдХреЗред
рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдмрд╕ рдЕрдкрдиреЗ рдкреНрд░рд┐рдп рдЬреЗрдХ рд╕реЗ RxBinding рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрдЯрди рдХреА рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрддреЗ рд╣реИрдВ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЙрд╕ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддреЗ рд╣реИрдВред рдЬреИрд╕реЗ рд╣реА рдПрдХ рдХреНрд▓рд┐рдХ рд╣реЛрддрд╛ рд╣реИ, рдмрд╛рдЗрдВрдбрд░ рдИрд╡реЗрдВрдЯ рдХреЛ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдПрдХреНрд╢рдирдХреНрд░реЗрдЯрд░ рдХреЛ рднреЗрдЬ рджреЗрдЧрд╛, рдЬреЛ рд╣рдорд╛рд░реЗ рдПрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░реЗрдЧрд╛, рдЬреЛ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдПрдХ рдирдИ рд╕реНрдХреНрд░реАрди рдЦреЛрд▓реЗрдЧрд╛ред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдХреЛрдИ рд╕реНрд╡рд┐рдЪ рдирд╣реАрдВ рдереЗред рдЖрдЧреЗ рдореИрдВ рдХреЛрдб рдореЗрдВ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдХрд┐ рдРрд╕рд╛ рдХреНрдпреЛрдВ рд╣реИред
рдЕрдЧрд░ рд╣рдореЗрдВ рдЕрдЪрд╛рдирдХ рдиреЗрдЯрд╡рд░реНрдХ рдпрд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдЬрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рд╣рдо рдЗрди рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╡рд╣реАрдВ рдХрд░ рджреЗрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЙрди рдЗрдВрдЯрд░реИрдХреНрд╢рдирд░реНрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдордиреЗ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ ActionCreator рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рджрд┐рдпрд╛ рд╣реИ:
рдбрд┐рд╕реНрдХреНрд▓реЗрдорд░: рдХреЛрдб рдХрд╛ рдкреНрд░рд╛рд░реВрдкрдг рдпрд╣рд╛рдВ рдареАрдХ рдирд╣реАрдВ рд╣реИ, рдореЗрд░реЗ рдкрд╛рд╕ рд▓реЗрдЦ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХреЗ рдирд┐рдпрдо рд╣реИрдВ рддрд╛рдХрд┐ рдХреЛрдб рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдкрдврд╝рд╛ рдЬрд╛ рд╕рдХреЗред
class LoadItemsActionCreator( private val getItems: () -> Observable<List<ViewTyped>>, private val showLoadedItems: ActionMapper<DiffResult<ViewTyped>>, private val diffCalculator: DiffCalculator<ViewTyped>, private val errorItem: ErrorView, private val emptyItem: ViewTyped? = null) : ActionOnEvent
рд╢рдмреНрджреЛрдВ рджреНрд╡рд╛рд░рд╛ "рдЙрдирдХреЗ рдХреЙрд▓ рдХреЗ рдЗрдВрдЯрд░рдлреЗрд╕ рджреНрд╡рд╛рд░рд╛" рдореЗрд░рд╛ рдорддрд▓рдм рдмрд┐рд▓реНрдХреБрд▓ рдпрд╣реА рдерд╛ рдХрд┐ рдХреИрд╕реЗ getItems рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдпрд╣рд╛рдВ ViewTyped рд╕реВрдЪрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░рд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╣реИ)ред рд╡реИрд╕реЗ, рд╣рдордиреЗ рдЗрд╕ ActionCreator рдХреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдЖрда рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╣рд┐рд╕реНрд╕реЛрдВ рдореЗрдВ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдпрдерд╛рд╕рдВрднрд╡ рдмрд╣реБрдореБрдЦреА рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИред
рдЪреВрдВрдХрд┐ рдШрдЯрдирд╛рдПрдВ рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдкреНрд░рдХреГрддрд┐ рдХреА рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЕрдиреНрдп рдСрдкрд░реЗрдЯрд░реЛрдВ рдХреЛ рдЬреЛрдбрд╝рдХрд░ рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд▓реЛрдбрд┐рдВрдЧ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП startWith (showLoadingAction), рдФрд░ onErrorReturn (errorAction) рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде рд╕реНрдХреНрд░реАрди рд╕реНрдерд┐рддрд┐ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдПред
рдФрд░ рдпрд╣ рд╕рдм рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рддреНрдордХ рд╣реИ!
рдЙрджрд╛рд╣рд░рдг
class AboutFragment : CompositionFragment(R.layout.fragment_about) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val component = AboutComponent( setVersionName = { { appVersion.text = it } }, openPdfAction = { (url, name) -> { openPdf(url, name) } }) val events = AboutEventsImpl( bindEvent = bindEvent, openPolicyPrivacyEvent = confidentialityPolicy.clicks(), openProcessingPersDataEvent = personalDataProtection.clicks(), unbindEvent = unBindEvent) component.binder().bind(events) }
рдЖрдЗрдП рдЕрдВрдд рдореЗрдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЛ рджреЗрдЦреЗрдВред рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдЖрд╡реЗрджрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ - рд╕рдмрд╕реЗ рд╕рд░рд▓ рд╕реНрдХреНрд░реАрди рдореЗрдВ рд╕реЗ рдПрдХ рдЪреБрдирд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдХреНрд░реАрди рд╣реИред
рдПрдХ рдШрдЯрдХ рдмрдирд╛рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
val component = AboutComponent( setVersionName = { { appVersion.text = it } }, openPdfAction = { (url, name) -> { openPdf(url, name) } } )
рдШрдЯрдХ рддрд░реНрдХ - рдХрд╛рд░реНрдп / ActionMappers - ActionCreators рдХреЗ рд╕рд╛рде рджреГрд╢реНрдп рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддреЗ рд╣реИрдВред ActionMapper'e setVersionName рдореЗрдВ рд╣рдо рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕ рдорд╛рди рдХреЛ рд╕реНрдХреНрд░реАрди рдкрд░ рдЯреЗрдХреНрд╕реНрдЯ рдХреЛ рдЕрд╕рд╛рдЗрди рдХрд░рддреЗ рд╣реИрдВред OpenPdfAction рдореЗрдВ, рдХрд┐рд╕реА рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдХреЗ рд▓рд┐рдВрдХ рдХреА рдПрдХ рдЬреЛрдбрд╝реА рдФрд░ рдЕрдЧрд▓реА рд╕реНрдХреНрд░реАрди рдХреЛ рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдирд╛рдо рдЬрд╣рд╛рдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрд╕ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдХреЛ рдкрдврд╝ рд╕рдХрддрд╛ рд╣реИред
рдпрд╣рд╛рдБ рдШрдЯрдХ рд╣реА рд╣реИ:
class AboutComponent( private val setVersionName: ActionMapper<String>, private val openPdfAction: ActionMapper<Pair<String, String>>) { fun binder(): AboutEventsBinder { val openPolicyPrivacy = OpenPdfActionCreator(openPdfAction, someUrlString) val openProcessingPersonalData = OpenPdfActionCreator(openPdfAction, anotherUrlString) val setVersionName = setVersionName.toSimpleActionCreator( moreComponent::currentVersionName ) return AboutEventsBinder(setVersionName, openPolicyPrivacy, openProcessingPersonalData) } }
рдореБрдЭреЗ рдЖрдкрдХреЛ рдпрд╛рдж рджрд┐рд▓рд╛рдирд╛ рд╣реИ рдХрд┐:
typealias Action = () -> Unit typealias ActionMapper<T> = (T) -> Action
рдареАрдХ рд╣реИ, рдЪрд▓реЛ рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред
fun binder(): AboutEventsBinder
рдЖрдЗрдП AboutEventsBinder рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рджреЗрдЦреЗрдВред
class AboutEventsBinder(private val setVersionName: ActionOnEvent, private val openPolicyPrivacy: ActionOnEvent, private val openProcessingPersonalData: ActionOnEvent) : BaseEventsBinder<AboutEvents>() { override fun bindInternal(events: AboutEvents): Observable<Action> { return Observable.merge( setVersionName(events.bindEvent), openPolicyPrivacy(events.openPolicyPrivacyEvent), openProcessingPersonalData(events.openProcessingPersDataEvent)) } }
ActionOnEvent рдПрдХ рдЕрдиреНрдп рдЯрд╛рдЗрдкреЗрд▓рд┐рдпрд╛рд╕ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рд░ рдмрд╛рд░ рд▓рд┐рдЦрдирд╛ рдирд╣реАрдВ рд╣реИред
ActionCreator<Observable<*>>
AboutEventsBinder рдореЗрдВ, рд╣рдо ActionCreators рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рдФрд░, рдЙрдиреНрд╣реЗрдВ рдЗрдирд╡реЙрдЗрд╕ рдХрд░рддреЗ рд╣реБрдП, рдПрдХ рд╡рд┐рд╢реЗрд╖ рдИрд╡реЗрдВрдЯ рдореЗрдВ рдмрд╛рдБрдзрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдпрд╣ рд╕рдм рдХреИрд╕реЗ рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рдЖрдЗрдП рдЖрдзрд╛рд░ рд╡рд░реНрдЧ - рдмреЗрд╕рдЗрд╡реИрдВрдЯреНрд╕рдмрд╛рдЗрдВрдбрд░ рдХреЛ рджреЗрдЦреЗрдВред
abstract class BaseEventsBinder<in EVENTS : BaseEvents>( private val uiScheduler: Scheduler = AndroidSchedulers.mainThread() ) { fun bind(events: EVENTS) { bindInternal(events).observeOn(uiScheduler) .takeUntil(events.unbindEvent) .subscribe(Action::invoke) } protected abstract fun bindInternal(events: EVENTS): Observable<Action> }
рд╣рдо рдкрд░рд┐рдЪрд┐рдд рдмрд╛рдЗрдВрдбреЗрдВрдЯ рд╡рд┐рдзрд┐ рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ рд╣рдордиреЗ рдЙрддреНрддрд░рд╛рдзрд┐рдХрд╛рд░реА рдореЗрдВ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рд╣реИред рдЕрдм рдмрд╛рдЗрдВрдб рд╡рд┐рдзрд┐ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рд╕рд╛рд░рд╛ рдЬрд╛рджреВ рдпрд╣рд╛рдВ рд╣реИред рд╣рдо BaseEvents рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рдЙрддреНрддрд░рд╛рдзрд┐рдХрд╛рд░реА рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕реЗ рдШрдЯрдирд╛рдХреНрд░рдо рдФрд░ рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП bindInternal рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред рдПрдХ рдмрд╛рд░ рдЬрдм рд╣рдо рдХрд╣рддреЗ рд╣реИрдВ рдХрд┐ рдЬреЛ рднреА рдЖрддрд╛ рд╣реИ, рд╣рдо ui- рд╕реНрдЯреНрд░реАрдо рдкрд░ рдЕрдорд▓ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрддреЗ рд╣реИрдВред рд╣рдо рдПрдХ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИрдХ рднреА рджреЗрдЦрддреЗ рд╣реИрдВ - takeUntilред
interface BaseEvents { val unbindEvent: EventObservable }
рдЖрдзрд╛рд░рд╡рд┐рд╣реАрди рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдЕрд╕рдВрдмрджреНрдз рдХреНрд╖реЗрддреНрд░ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЗрд╕реЗ рд╕рднреА рд╡рд╛рд░рд┐рд╕реЛрдВ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рдЕрджреНрднреБрдд рдлрд╝реАрд▓реНрдб рдЖрдкрдХреЛ рдЗрд╕ рдИрд╡реЗрдВрдЯ рдХреЗ рдкреВрд░рд╛ рд╣реЛрддреЗ рд╣реА рдЪреЗрди рд╕реЗ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдпрд╣ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИ! рдЕрдм рдЖрдк рдХрд╛ рдкрд╛рд▓рди рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЬреАрд╡рди рдЪрдХреНрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд┐рдВрддрд╛ рди рдХрд░реЗрдВ рдФрд░ рд╢рд╛рдВрддрд┐ рд╕реЗ рд╕реЛрдПрдВред
val openPolicyPrivacy = OpenPdfActionCreator(openPdfAction, policyPrivacyUrl) val openProcessingPersonalData = OpenPdfActionCreator(openPdfAction, personalDataUrl)
рдШрдЯрдХ рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВред рдФрд░ рдпрд╣рд╛рдВ рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкреБрди: рдЙрдкрдпреЛрдЧ рдХреА рд╡рд┐рдзрд┐ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдордиреЗ рдПрдХ рд╡рд░реНрдЧ рд▓рд┐рдЦрд╛ рд╣реИ рдЬреЛ рдкреАрдбреАрдПрдл рджреЗрдЦрдиреЗ рдХреА рд╕реНрдХреНрд░реАрди рдЦреЛрд▓ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдХреЛрдИ рдорд╛рдпрдиреЗ рдирд╣реАрдВ рд░рдЦрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХреНрдпрд╛ рд╣реИред рдХреЛрдИ рдХреЛрдб рджреЛрд╣рд░рд╛рд╡ рдирд╣реАрдВред
class OpenPdfActionCreator( private val openPdfAction: ActionMapper<Pair<String, String>>, private val pdfUrl: String) : ActionOnEvent { override fun invoke(event: EventObservable): Observable<Action> { return event.map { openPdfAction(pdfUrl to pdfUrl.substringAfterLast(FILE_NAME_DELIMITER)) } } }
ActionCreator рдХреЛрдб рднреА рдпрдерд╛рд╕рдВрднрд╡ рд╕рд░рд▓ рд╣реИ, рдпрд╣рд╛рдБ рд╣рдо рдХреБрдЫ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдЬреЛрдбрд╝рддреЛрдбрд╝ рдХрд░рддреЗ рд╣реИрдВред
рдЖрдЗрдП рдШрдЯрдХ рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд ActionCreator рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
setVersionName.toSimpleActionCreator(moreComponent::currentVersionName)
рдПрдХ рдмрд╛рд░ рд╣рдо рднреА рд╡рд╣реА рдФрд░ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рд╕рд░рд▓ ActionCreators рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд▓рд╕реА рд╣реЛ рдЧрдПред рд╣рдордиреЗ рдХреЛрдЯрд▓рд┐рди рдХреА рд╢рдХреНрддрд┐ рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдФрд░ рд╡рд┐рд╕реНрддрд╛рд░ рд▓рд┐рдЦрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдореЗрдВ ActionMapper рдХреЛ рдПрдХ рд╕реНрдерд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
fun <R> ActionMapper<R>.toSimpleActionCreator( mapper: () -> R): ActionCreator<Observable<*>> { return object : ActionCreator<Observable<*>> { override fun invoke(event: Observable<*>): Observable<Action> { return event.map { this@toSimpleActionCreator(mapper()) } } } }
рдРрд╕реЗ рд╕рдордп рд╣реЛрддреЗ рд╣реИрдВ рдЬрдм рд╣рдореЗрдВ рдХреБрдЫ рднреА рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рдХреБрдЫ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВ - рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрди рд╕реНрдХреНрд░реАрди рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП:
fun Action.toActionCreator(): ActionOnEvent { return object : ActionOnEvent { override fun invoke(event: EventObservable): Observable<Action> { return event.map { this@toActionCreator } } } }
рдЗрд╕рд▓рд┐рдП, рдШрдЯрдХ рдХреЗ рд╕рд╛рде, рдЦрдВрдб рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВ:
val events = AboutEventsImpl( bindEvent = bindEvent, openPolicyPrivacyEvent = confidentialityPolicy.throttleFirstClicks(), openProcessingPersDataEvent = personalDataProtection.throttleFirstClicks(), unbindEvent = unBindEvent)
рдпрд╣рд╛рдВ рд╣рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗ рдШрдЯрдирд╛рдУрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдПрдХ рд╡рд░реНрдЧ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВред рдФрд░ рдЕрдирдмрд╛рдЗрдВрдб рдФрд░ рдмрд╛рдЗрдВрдб рдХреЗрд╡рд▓ рд╕реНрдХреНрд░реАрди рдЬреАрд╡рди-рдЪрдХреНрд░ рдХреА рдШрдЯрдирд╛рдПрдВ рд╣реИрдВ рдЬреЛ рд╣рдо рдЯреНрд░реЗрд▓реЛ рдХреА рдирд╡реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЙрдард╛рддреЗ рд╣реИрдВред
fun <T> NaviComponent.observe(event: Event<T>): Observable<T> = RxNavi.observe(this, event) val unBindEvent: Observable<*> = observe(Event.DESTROY_VIEW) val bindEvent: Observable<*> = Observable.just(true) val bindEvent = observe(Event.POST_CREATE)
рдИрд╡реЗрдВрдЯреНрд╕ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╕реНрдХреНрд░реАрди рдХреА рдШрдЯрдирд╛рдУрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рдЗрд╕реЗ рдмреЗрд╕рдЗрд╡реЗрдиреНрдЯреНрд╕ рдХрд╛ рд╡рд╛рд░рд┐рд╕ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣рдореЗрд╢рд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдШрдЯрдирд╛рдПрдБ рд╕реНрдХреНрд░реАрди рдкрд░ рдЖрдиреЗ рд╡рд╛рд▓реЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдХреЗ рдмрд╛рдж рдПрдХ рд╣реЛрдиреЗ рд▓рдЧреАрдВ, рд▓реЗрдХрд┐рди рдРрд╕рд╛ рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рджреЛ рдШрдЯрдирд╛рдУрдВ рдХреЛ рдПрдХ рд╕рд╛рде рд░рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЦреЛрд▓рдиреЗ рдФрд░ рдлрд┐рд░ рд╕реЗ рд▓реЛрдб рдХрд░рдиреЗ рдкрд░ рд╕реНрдХреНрд░реАрди рд▓реЛрдб рд╣реЛрдиреЗ рдХреА рдШрдЯрдирд╛рдУрдВ рдХреЛ рдПрдХ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП - рдмрд╕ рд╕реНрдХреНрд░реАрди рд▓реЛрдб рдХрд░рдирд╛ред
interface AboutEvents : BaseEvents { val bindEvent: EventObservable val openPolicyPrivacyEvent: EventObservable val openProcessingPersDataEvent: EventObservable } class AboutEventsImpl(override val bindEvent: EventObservable, override val openPolicyPrivacyEvent: EventObservable, override val openProcessingPersDataEvent: EventObservable, override val unbindEvent: EventObservable) : AboutEvents
рд╣рдо рдЯреБрдХрдбрд╝реЗ рдкрд░ рд▓реМрдЯрддреЗ рд╣реИрдВ рдФрд░ рд╕рдм рдХреБрдЫ рдПрдХ рд╕рд╛рде рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ! рд╣рдо рдШрдЯрдХ рдХреЛ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмрд╛рдЗрдВрдбрд░ рдмрдирд╛рдиреЗ рдФрд░ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рддреЗ рд╣реИрдВ, рдлрд┐рд░ рд╣рдо рдЙрд╕ рдкрд░ рдмрд╛рдЗрдВрдб рд╡рд┐рдзрд┐ рдХрд╣рддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдВ рд╣рдо рд╕реНрдХреНрд░реАрди рдШрдЯрдирд╛рдУрдВ рдХреЛ рджреЗрдЦрдиреЗ рд╡рд╛рд▓реА рд╡рд╕реНрддреБ рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред
component.binder().bind(events)
рд╣рдо рд▓рдЧрднрдЧ рджреЛ рд╡рд░реНрд╖реЛрдВ рд╕реЗ рдЗрд╕ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдкрд░ рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд▓рд┐рдЦ тАЛтАЛрд░рд╣реЗ рд╣реИрдВред рдФрд░ рдлреАрдЪрд░ рд╢реЗрдпрд░рд┐рдВрдЧ рдХреА рдЧрддрд┐ рдореЗрдВ рдкреНрд░рдмрдВрдзрдХреЛрдВ рдХреА рдЦреБрд╢реА рдХреА рдХреЛрдИ рд╕реАрдорд╛ рдирд╣реАрдВ рд╣реИ! рдЙрдирдХреЗ рдкрд╛рд╕ рдПрдХ рдирдП рдХреЗ рд╕рд╛рде рдЖрдиреЗ рдХрд╛ рд╕рдордп рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкреБрд░рд╛рдиреЗ рдЦрддреНрдо рдХрд░ рд░рд╣реЗ рд╣реИрдВред рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдмрд╣реБрдд рд▓рдЪреАрд▓рд╛ рд╣реИ рдФрд░ рдЖрдкрдХреЛ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдХреЛрдб рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рдЗрд╕ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЗ рдиреБрдХрд╕рд╛рди рдХреЛ рд░рд╛рдЬреНрдп рдХрд╛ рдЧреИрд░-рд╕рдВрд░рдХреНрд╖рдг рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╕рдВрдкреВрд░реНрдг рдореЙрдбрд▓ рдирд╣реАрдВ рд╣реИ рдЬреЛ рд╕реНрдХреНрд░реАрди рдХреА рд╕реНрдерд┐рддрд┐ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рдПрдорд╡реАрдЖрдИ рдореЗрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо рдЗрд╕реЗ рд╕рдВрднрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВред рдЬреИрд╕реЗ - рдиреАрдЪреЗ рджреЗрдЦреЗрдВред
рдЕрдзреНрдпрд╛рдп 4. рдмреЛрдирд╕
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рд░ рдХреЛрдИ рд╡рд┐рд╢реНрд▓реЗрд╖рд┐рдХреА рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рдЬрд╛рдирддрд╛ рд╣реИ: рдХреЛрдИ рднреА рдЗрд╕реЗ рд▓рд┐рдЦрдирд╛ рдкрд╕рдВрдж рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕рднреА рдкрд░рддреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХреНрд░реЙрд▓ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЪреБрдиреМрддрд┐рдпреЛрдВ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рддрд╛ рд╣реИред рдХреБрдЫ рд╕рдордп рдкрд╣рд▓реЗ, рдФрд░ рд╣рдореЗрдВ рдЗрд╕рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛ред рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдПрдХ рдмрд╣реБрдд рд╣реА рд╕реБрдВрджрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред
рддреЛ, рдореЗрд░рд╛ рд╡рд┐рдЪрд╛рд░ рдХреНрдпрд╛ рдерд╛: рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдЬрд╡рд╛рдм рдореЗрдВ рдЖрдорддреМрд░ рдкрд░ рд╡рд┐рд╢реНрд▓реЗрд╖рд┐рдХреА рдирд┐рдХрд▓рддреА рд╣реИред рдФрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдмрд╕ рдПрдХ рд╡рд░реНрдЧ рд╣реИ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЬрдорд╛ рдХрд░рддрд╛ рд╣реИред рдареАрдХ рд╣реИ, рдЪрд▓реЛ рд╢реБрд░реВ рд╣реЛ рдЬрд╛рдУред
рдЪрд░рдг 1 рд╣рдо TrackAnalytics рдореЗрдВ рдШрдЯрдирд╛рдУрдВ рдХреЛ рд▓рдкреЗрдЯрдХрд░ BaseEventsBinder рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рдХреЛ рдереЛрдбрд╝рд╛ рдмрджрд▓ рджреЗрддреЗ рд╣реИрдВ:
abstract class BaseEventsBinder<in EVENTS : BaseEvents>( private val trackAnalytics: TrackAnalytics<EVENTS> = EmptyAnalyticsTracker(), private val uiScheduler: Scheduler = AndroidSchedulers.mainThread()) { @SuppressLint("CheckResult") fun bind(events: EVENTS) { bindInternal(trackAnalytics(events)).observeOn(uiScheduler) .takeUntil(events.unbindEvent) .subscribe(Action::invoke) } protected abstract fun bindInternal(events: EVENTS): Observable<Action> }
рдЪрд░рдг 2 рд╣рдо рдкрд┐рдЫрдбрд╝реЗ рд╕рдВрдЧрддрддрд╛ рдХреЛ рдмрдирд╛рдП рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдФрд░ рдЙрди рд╡рд╛рд░рд┐рд╕реЛрдВ рдХреЛ рдирд╣реАрдВ рддреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдЬрд┐рдиреНрд╣реЛрдВрдиреЗ рдЕрднреА рддрдХ рдПрдирд╛рд▓рд┐рдЯрд┐рдХреНрд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЯреНрд░реИрдХрдЕрдирд╛рд▓рд┐рдЯрд┐рдХреНрд╕ рдЪрд░ рдХрд╛ рдПрдХ рд╕реНрдерд┐рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдмрдирд╛рддреЗ рд╣реИрдВ:
interface TrackAnalytics<EVENTS : BaseEvents> { operator fun invoke(events: EVENTS): EVENTS } class EmptyAnalyticsTracker<EVENTS : BaseEvents> : TrackAnalytics<EVENTS> { override fun invoke(events: EVENTS): EVENTS = events }
рдЪрд░рдг 3 рд╣рдо рд╡рд╛рдВрдЫрд┐рдд рд╕реНрдХреНрд░реАрди рдХреЗ рд▓рд┐рдП TrackAnalytics рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓рд┐рдЦрддреЗ рд╣реИрдВ - рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╕реВрдЪреА рд╕реНрдХреНрд░реАрди рдХреЗ рд▓рд┐рдП:
class TrackProjectsEvents : TrackAnalytics<ProjectsEvents> { override fun invoke(events: ProjectsEvents): ProjectsEvents { return object : ProjectsEvents by events { override val boardClickEvent = events.boardClickEvent.trackTypedEvent { allProjectsProjectClick(it.title) } override val openBoardCreationEvent = events.openBoardCreationEvent.trackEvent { allProjectsAddProjectClick() } override val openCardsSearchEvent = events.openCardsSearchEvent.trackEvent { allProjectsSearchBarClick() } } } }
рдпрд╣рд╛рдБ рд╣рдо рдлрд┐рд░ рд╕реЗ рдкреНрд░рддрд┐рдирд┐рдзрд┐рдпреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдХреЛрдЯрд▓рд┐рди рдХреА рд╢рдХреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдЗрдирд╣реЗрд░рд┐рдЯрд░ рд╣реИ - рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ ProjectEventsред рд▓реЗрдХрд┐рди рдХреБрдЫ рдШрдЯрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЗрд╕ рдмрд╛рдд рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдХреИрд╕реЗ рдЗрд╡реЗрдВрдЯ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдПрдирд╛рд▓рд┐рдЯрд┐рдХреНрд╕ рднреЗрдЬрдиреЗ рдХреЗ рд╕рд╛рде рдЙрдирдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ рдПрдХ рдмрдВрдзрди рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, trackEvent рд╕рд┐рд░реНрдл doOnNext рд╣реИ:
inline fun <T> Observable<T>.trackEvent(crossinline event: AnalyticsSpec.() -> Unit): Observable<T> = doOnNext { event(analyticsSpec) } inline fun <T> Observable<T>.trackTypedEvent(crossinline event: AnalyticsSpec.(T) -> Unit): Observable<T> = doOnNext { event(analyticsSpec, it) }
рдЪрд░рдг 4 рдЗрд╕реЗ рдмрд┐рдВрджрд░ рдХреЛ рд╣рд╕реНрддрд╛рдВрддрд░рд┐рдд рдХрд░рдирд╛ рдмрд╛рдХреА рд╣реИред рдЪреВрдВрдХрд┐ рд╣рдо рдЗрд╕реЗ рдПрдХ рдШрдЯрдХ рдореЗрдВ рдмрдирд╛рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрд╡рд╕рд░ рд╣реИ, рдЕрдЧрд░ рдЖрдкрдХреЛ рдЕрдЪрд╛рдирдХ рдирд┐рд░реНрдорд╛рдгрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд рдирд┐рд░реНрднрд░рддрд╛ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЕрдм ProjectEventsBinder рдирд┐рд░реНрдорд╛рддрд╛ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:
class ProjectsEventsBinder( private val loadItems: LoadItemsActionCreator, private val refreshBoards: ActionOnEvent, private val openBoard: ActionCreator<Observable<BoardId>>, private val openScreen: ActionOnEvent, private val openCardSearch: ActionOnEvent, trackAnalytics: TrackAnalytics<ProjectsEvents>) : BaseEventsBinder<ProjectsEvents>(trackAnalytics)
рдЖрдк GitHub рдкрд░ рдЕрдиреНрдп рдЙрджрд╛рд╣рд░рдг рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред
рдХреНрдпреВ рдПрдВрдб рдП
рдЖрдк рд╕реНрдХреНрд░реАрди рдХреА рд╕реНрдерд┐рддрд┐ рдХреИрд╕реЗ рд░рдЦрддреЗ рд╣реИрдВ?рдХреЛрдИ рд░рд╛рд╕реНрддрд╛ рдирд╣реАрдВред рд╣рдо рдУрд░рд┐рдПрдВрдЯреЗрд╢рди рдХреЛ рдмреНрд▓реЙрдХ рдХрд░рддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рд╣рдо рддрд░реНрдХреЛрдВ / рдЗрд░рд╛рджреЛрдВ рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╡рд╣рд╛рдВ OPENED_FROM_BACKSTACK рдЪрд░ рдмрдЪрд╛рддреЗ рд╣реИрдВред рдФрд░ рдмрд┐рдВрджрд░ рдХреЛ рдбрд┐рдЬрд╛рдЗрди рдХрд░рддреЗ рд╕рдордп, рд╣рдо рдЗрд╕реЗ рджреЗрдЦрддреЗ рд╣реИрдВред рдпрджрд┐ рдпрд╣ рдЧрд▓рдд рд╣реИ - рдиреЗрдЯрд╡рд░реНрдХ рд╕реЗ рдбреЗрдЯрд╛ рд▓реЛрдб рдХрд░реЗрдВред рдЕрдЧрд░ рд╕рдЪ рд╣реИ - рдХреИрд╢ рд╕реЗред рдЗрд╕рд╕реЗ рдЖрдк рд╕реНрдХреНрд░реАрди рдХреЛ рдЬрд▓реНрджреА рд╕реЗ рд░реАрдХреНрд░рд┐рдПрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЙрди рд╕рднреА рдХреЗ рд▓рд┐рдП рдЬреЛ рдУрд░рд┐рдПрдВрдЯреЗрд╢рди рдмреНрд▓реЙрдХрд┐рдВрдЧ рдХреЗ рдЦрд┐рд▓рд╛рдл рд╣реИрдВ: рдЕрдкрдиреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдлреЛрди рдХреЛ рдХрд┐рддрдиреА рдмрд╛рд░ рдЪрд╛рд▓реВ рдХрд░рдиреЗ рдФрд░ рдХрд┐рддрдиреЗ рдЕрд▓рдЧ рдУрд░рд┐рдПрдВрдЯреЗрд╢рди рдореЗрдВ рд╣реИрдВ, рдЗрд╕ рдкрд░ рдПрдирд╛рд▓рд┐рдЯрд┐рдХреНрд╕ рдХреЛ рдЬрд╛рдВрдЪрдиреЗ рдФрд░ рдЬрдорд╛ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдкрд░рд┐рдгрд╛рдо рдЖрд╢реНрдЪрд░реНрдпрдЪрдХрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдореИрдВ рдШрдЯрдХреЛрдВ рдХреЛ рд▓рд┐рдЦрдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддрд╛, рдореИрдВ рдЦрдВрдЬрд░ рд╕реЗ рджреЛрд╕реНрддреА рдХреИрд╕реЗ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ?рдореИрдВ рд╕рд▓рд╛рд╣ рдирд╣реАрдВ рджреЗрддрд╛, рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк рд╕рдВрдХрд▓рди рд╕рдордп рдкрд░ рдмреБрд░рд╛ рдирд╣реАрдВ рдорд╛рдирддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдПрдХ рдЦрдВрдЬрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рднреА рдШрдЯрдХ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рд╣рдордиреЗ рдХреЛрд╢рд┐рд╢ рдирд╣реАрдВ рдХреАред
рдореИрдВ рдХреЛрдЯрд▓рд┐рди рдореЗрдВ рдирд╣реАрдВ рд▓рд┐рдЦрддрд╛, рдЬрд╛рд╡рд╛ рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрдард┐рдирд╛рдЗрдпрд╛рдБ рд╣реИрдВ?рд╕рднреА рдПрдХ рд╣реА рдЬрд╛рд╡рд╛ рдореЗрдВ рд▓рд┐рдЦреЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдмрд╕ рдпрд╣ рдЗрддрдирд╛ рд╕реБрдВрджрд░ рдирд╣реАрдВ рд▓рдЧреЗрдЧрд╛ред
рдпрджрд┐ рдЖрдк рд▓реЗрдЦ рдкрд╕рдВрдж рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЕрдЧрд▓рд╛ рднрд╛рдЧ рдЗрд╕ рддрд░рд╣ рдХреА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдкрд░ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реЛрдЧрд╛ (рдлрд┐рд░ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЬрд╛рдПрдЧрд╛ рдХрд┐ рдЗрддрдиреЗ рд╕рд╛рд░реЗ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреНрдпреЛрдВ рд╣реИрдВ)ред Spoiler - рд▓рд┐рдЦрдирд╛ рдЖрд╕рд╛рди рд╣реИ рдФрд░ рдЖрдк рдШрдЯрдХ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рд╕рднреА рдкрд░рддреЛрдВ рдкрд░ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рдЗрд╕рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдпрд╣ рд╕рд┐рд░реНрдл рдПрдХ рдмрд╛рдВрдзрдиреЗ рд╡рд╛рд▓реА рд╡рд╕реНрддреБ рдмрдирд╛рддрд╛ рд╣реИред
рдЗрд╕ рд▓реЗрдЦ рдХреЛ рд▓рд┐рдЦрдиреЗ рдореЗрдВ рдЙрдирдХреА рдорджрдж рдХреЗ рд▓рд┐рдП рдЯрд┐рдВрдХреЙрдл рдмрд┐рдЬрдиреЗрд╕ рдореЛрдмрд╛рдЗрд▓ рдбреЗрд╡рд▓рдкрдореЗрдВрдЯ рдЯреАрдо рдХреЗ рд╕рд╣рдпреЛрдЧрд┐рдпреЛрдВ рдХрд╛ рдзрдиреНрдпрд╡рд╛рджред