MVVM рдореЗрдВ ViewModel рд╕реЗ рд▓реЗрдХрд░ рдЧрддрд┐рд╡рд┐рдзрд┐ / рдлреНрд░реИрдЧрдореЗрдВрдЯ рддрдХ рдХреА рдШрдЯрдирд╛рдУрдВ рдХреЛ рднреЗрдЬрдирд╛

рдЖрдЬ рд╣рдо MVVM рдореЗрдВ рдЧрддрд┐рд╡рд┐рдзрд┐рдпреЛрдВ / рдлрд╝реНрд░реИрдЧрдореЗрдВрдЯ рдФрд░ ViewModel рдХреЗ рдмреАрдЪ рдШрдЯрдирд╛рдУрдВ рдХрд╛ рдЖрджрд╛рди-рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗред ViewModel рд╕реЗ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдЕрдиреБрд╢рдВрд╕рд╛ рдХреА рдЬрд╛рддреА рд╣реИ рдХрд┐ рджреГрд╢реНрдпрдореЙрдбрд▓ рдореЗрдВ LiveData рдбреЗрдЯрд╛ рдореЗрдВ рдЧрддрд┐рд╡рд┐рдзрд┐ / рдлрд╝реНрд░реИрдЧрдореЗрдВрдЯ рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрдВред рд▓реЗрдХрд┐рди рдПрдХрд▓ (рдФрд░ рди рдХреЗрд╡рд▓) рдШрдЯрдирд╛рдУрдВ рдХреЛ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рдХрд░реЗрдВ, рдЬреИрд╕реЗ рдХрд┐ рдПрдХ рдЕрдзрд┐рд╕реВрдЪрдирд╛ рджрд┐рдЦрд╛рдПрдВ рдпрд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдФрд░ рдЯреБрдХрдбрд╝рд╛ рдЦреЛрд▓реЗрдВ?



рдЗрд╕рд▓рд┐рдП рд╕рднреА рдХреЛ рдирдорд╕реНрдХрд╛рд░!

рдореЗрд░рд╛ рдирд╛рдо рдЕрд▓реЗрдХреНрд╕реА рд╣реИ, рдореИрдВ Home Credit Bank рдореЗрдВ рдПрдХ Android рдбреЗрд╡рд▓рдкрд░ рд╣реВрдВред

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ ViewModels рд╕реЗ рд▓реЗрдХрд░ Views (рдХреНрд░рд┐рдпрд╛рдПрдБ / Fragments) рддрдХ рдХреА рдШрдЯрдирд╛рдУрдВ рдХреЛ рднреЗрдЬрдиреЗ рдФрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рд╣рдорд╛рд░рд╛ рддрд░реАрдХрд╛ рд╕рд╛рдЭрд╛ рдХрд░реВрдБрдЧрд╛ред

рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдореЗрдВ "рд╣реЛрдо рдХреНрд░реЗрдбрд┐рдЯ рдмреИрдВрдХ рд╕реЗ рдХрд┐рд╕реНрдд рдорд╛рд▓" рд╣рдо рдЯреБрдХрдбрд╝реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЙрдирдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдЧрддрд┐рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рднреА рд╕рдм рдХреБрдЫ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд╣реИред

рд╣рдо рдХреНрдпрд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ?


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

рдФрд░ рдХреНрдпрд╛, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рдорд╕реНрдпрд╛ рд╣реИ?


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

Fragments рдФрд░ ViewModels рдХреЗ рдмреАрдЪ рдмрд╛рддрдЪреАрдд рдХреЗ рд▓рд┐рдП рдорд╛рдирдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг ViewModel рдореЗрдВ рд╕реНрдерд┐рдд LiveData рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрдирд╛ рд╣реИред LiveData рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реАрдзреЗ рдШрдЯрдирд╛рдУрдВ рдХреЛ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░рдирд╛ рдЕрд╕рдВрднрд╡ рд╣реИ, рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рдХрд┐ рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдзреНрдпрд╛рди рдореЗрдВ рдирд╣реАрдВ рд░рдЦрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдШрдЯрдирд╛ рдкрд╣рд▓реЗ рд╣реА рдкреВрд░реА рд╣реЛ рдЪреБрдХреА рд╣реИ рдпрд╛ рдирд╣реАрдВред

рдХреНрдпрд╛ рд╕рдорд╛рдзрд╛рди рдореМрдЬреВрдж рд╣реИрдВ:


1. SingleLiveEvent рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
рдкреЗрд╢реЗрд╡рд░реЛрдВ: рдШрдЯрдирд╛ рдХреЛ рдПрдХ рдмрд╛рд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рд╡рд┐рдкрдХреНрд╖: рдПрдХ рдШрдЯрдирд╛ - рдПрдХ SingleLiveEvent ред рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдШрдЯрдирд╛рдУрдВ рдХреЗ рд╕рд╛рде, рдПрди рдЗрд╡реЗрдВрдЯ-рдСрдмреНрдЬреЗрдХреНрдЯ рд╡реНрдпреВрдореЙрдбрд▓ рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЛ рдЯреБрдХрдбрд╝реЗ рдореЗрдВ рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдм рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред

2. рдПрдХ рдЕрдЪреНрдЫрд╛ рдЙрджрд╛рд╣рд░рдг ред
рдкреЗрд╢реЗрд╡рд░реЛрдВ: рдПрдХ рдШрдЯрдирд╛ рдХреЛ рдПрдХ рдмрд╛рд░ рднреА рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЖрдк рдбреЗрдЯрд╛ рдХреЛ рд╡реНрдпреВрдХреЛрдб рд╕реЗ рдЯреБрдХрдбрд╝реЗ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рд╡рд┐рдкрдХреНрд╖: рдШрдЯрдирд╛ рдореЗрдВ рдбреЗрдЯрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдкрдХреЛ рдбреЗрдЯрд╛ рдХреЗ рдмрд┐рдирд╛ рдХрд┐рд╕реА рдШрдЯрдирд╛ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (val content: T) , рддреЛ рдЖрдкрдХреЛ рдПрдХ рдФрд░ рд╡рд░реНрдЧ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдпрд╣ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдШрдЯрдирд╛ рдХреЛ рдПрдХ рдмрд╛рд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ (рдШрдЯрдирд╛ рдХреЛ рдПрдХ рдмрд╛рд░ рд╣реА рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреА рдШрдЯрдирд╛ рдХреЛ рдХрдИ рдмрд╛рд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдЗрд╕реЗ рд╡реНрдпреВрдореЙрдбрд▓ рд╕реЗ рдЪрд▓рд╛рддреЗ рд╣реИрдВ)ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрди-рдЕрдиреБрд░реЛрдз рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд░реВрдк рд╕реЗ рдЪрд▓рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХреЛрдИ рдиреЗрдЯрд╡рд░реНрдХ рдирд╣реАрдВ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдиреЗрдЯрд╡рд░реНрдХ рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рдПрдЧрд╛, рдФрд░ рдиреЗрдЯрд╡рд░реНрдХ рддреНрд░реБрдЯрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрди рдШрдЯрдирд╛рдУрдВ рдХреЗ рдПрдХ рдЯреБрдХрдбрд╝реЗ рдореЗрдВ рдЦреАрдВрдЪ рд▓реЗрдЧрд╛, рдПрди рдЕрд▓рд░реНрдЯ рдЯреБрдХрдбрд╝реЗ рдореЗрдВ рдЦреБрд▓ рдЬрд╛рдПрдЧрд╛ред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрд╕ рддрд░рд╣ рдХреЗ рдирд┐рд░реНрдгрдп рдХреЛ рдордВрдЬреВрд░реА рдирд╣реАрдВ рджреЗрдЧрд╛ :)ред рд╣рдореЗрдВ рдЗрд╕ рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде рдПрдХ рдмрд╛рд░ рд╕рдВрджреЗрд╢ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЖрдпреЛрдЬрди рдХреЛ рдПрдХ рдмрд╛рд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдирд┐рд░реНрдгрдп


рд╣рдо рдЖрдзрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдШрдЯрдирд╛ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреА рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП SingleLiveEvent рдХрд╛ рд╡рд┐рдЪрд╛рд░ рд▓реЗрддреЗ рд╣реИрдВред

рд╕рдВрднрд╛рд╡рд┐рдд рдИрд╡реЗрдВрдЯ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ


 enum class Type { EXECUTE_WITHOUT_LIMITS, //    тАУ   ,             EXECUTE_ONCE, //      WAIT_OBSERVER_IF_NEEDED,//    ,     -       WAIT_OBSERVER_IF_NEEDED_AND_EXECUTE_ONCE //    ,     -           } 

рдПрдХ рдИрд╡реЗрдВрдЯ рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рдмрдирд╛рдПрдВ - NavigationEvent


isHandled рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдШрдЯрдирд╛ рдкреНрд░рд╛рдкреНрдд рд╣реБрдИ рдереА (рд╣рдо рдорд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдпрджрд┐ рдкрд░реНрдпрд╡реЗрдХреНрд╖рдХ рдХреЛ рдЯреБрдХрдбрд╝реЗ рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рд╣реБрдЖ рдерд╛)ред

 open class NavigationEvent(var isHandled: Boolean = false, var type: Events.Type) 

рдПрдХ Emitter рд╡рд░реНрдЧ рдмрдирд╛рдПрдВ - Emitter


рдЗрд╡реЗрдВрдЯ рдПрдорд┐рдЯрд░ рдХреНрд▓рд╛рд╕ рдХреЛ LiveData < NavigationEvent > рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИред рдЗрд╕ рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ ViewModel рдореЗрдВ рдШрдЯрдирд╛рдУрдВ рдХреЛ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

 class Emitter : MutableLiveData<NavigationEvent>() { private val waitingEvents: ArrayList<NavigationEvent> = ArrayList() private var isActive = false override fun onInactive() { isActive = false } override fun onActive() { isActive = true val postingEvents = ArrayList<NavigationEvent>() waitingEvents .forEach { if (hasObservers()) { this.value = it postingEvents.add(it) } }.also { waitingEvents.removeAll(postingEvents) } } private fun newEvent(event: NavigationEvent, type: Type) { event.type = type this.value = when (type) { Type.EXECUTE_WITHOUT_LIMITS, Type.EXECUTE_ONCE -> if (hasObservers()) event else null Type.WAIT_OBSERVER_IF_NEEDED, Type.WAIT_OBSERVER_IF_NEEDED_AND_EXECUTE_ONCE -> { if (hasObservers() && isActive) event else { waitingEvents.add(event) null } } } } /** Clear All Waiting Events */ fun clearWaitingEvents() = waitingEvents.clear() } 

isActive - рд╣рдореЗрдВ рдпрд╣ рд╕рдордЭрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдХрдо рд╕реЗ рдХрдо рдПрдХ Observer рдХреЛ Emitter рд╕рджрд╕реНрдпрддрд╛ рджреА рдЧрдИ рд╣реИред рдФрд░ рдЙрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдЬрдм рдЧреНрд░рд╛рд╣рдХ рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛ рд╣реИ рдФрд░ рдЙрд╕рдХреЗ рдЗрдВрддрдЬрд╛рд░ рдХреА рдШрдЯрдирд╛рдПрдВ рдЬрдорд╛ рд╣реЛ рдЧрдИ рд╣реИрдВ, рд╣рдо рдЗрди рдШрдЯрдирд╛рдУрдВ рдХреЛ рднреЗрдЬрддреЗ рд╣реИрдВред рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг: рдИрд╡реЗрдВрдЯ рднреЗрдЬрдирд╛ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИред рдпрд╣ this.postValue(event) рдорд╛рдзреНрдпрдо рд╕реЗ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рд╕реЗрдЯрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕ this.value = event ред рдЕрдиреНрдпрдерд╛, рдЧреНрд░рд╛рд╣рдХ рдХреЛ рд╕реВрдЪреА рдореЗрдВ рдХреЗрд╡рд▓ рдЕрдВрддрд┐рдо рдШрдЯрдирд╛ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдЧреАред

рдПрдХ рдирдИ рдШрдЯрдирд╛ рднреЗрдЬрдиреЗ рдХреА рд╡рд┐рдзрд┐, newEvent(event, type) , рджреЛ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ - рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдШрдЯрдирд╛ рд╕реНрд╡рдпрдВ рдФрд░ рдЗрд╕ рдШрдЯрдирд╛ рдХрд╛ рдкреНрд░рдХрд╛рд░ред

рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреА рдШрдЯрдирд╛рдУрдВ (рд▓рдВрдмреЗ рдирд╛рдореЛрдВ) рдХреЛ рдпрд╛рдж рди рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рддрд░реАрдХреЗ рдмрдирд╛рдПрдВрдЧреЗ рдЬреЛ рдХреЗрд╡рд▓ рдШрдЯрдирд╛ рдХреЛ рд╣реА рд╕реНрд╡реАрдХрд╛рд░ рдХрд░реЗрдВрдЧреЗ:

 class Emitter : MutableLiveData<NavigationEvent>() { тАж /** Default: Emit Event for Execution */ fun emitAndExecute(event: NavigationEvent) = newEvent(event, Type.EXECUTE_WITHOUT_LIMITS) /** Emit Event for Execution Once */ fun emitAndExecuteOnce(event: NavigationEvent) = newEvent(event, Type.EXECUTE_ONCE) /** Wait Observer Available and Emit Event for Execution */ fun waitAndExecute(event: NavigationEvent) = newEvent(event, Type.WAIT_OBSERVER_IF_NEEDED) /** Wait Observer Available and Emit Event for Execution Once */ fun waitAndExecuteOnce(event: NavigationEvent) = newEvent(event, Type.WAIT_OBSERVER_IF_NEEDED_AND_EXECUTE_ONCE) } 

рдФрдкрдЪрд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ, рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА ViewModel рдореЗрдВ Emitter рдХреЛ рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдм рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрдирдХреЗ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ рдИрд╡реЗрдВрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдИрд╡реЗрдВрдЯ рдХреЛ рдкрд╣рд▓реЗ рд╣реА рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рдЪреБрдХрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВ)ред

рдПрдХ рдЗрд╡реЗрдВрдЯ рдСрдмреНрдЬрд░реНрд╡рд░ рдХреНрд▓рд╛рд╕ рдмрдирд╛рдПрдВ - EventObserver


 class EventObserver(private val handlerBlock: (NavigationEvent) -> Unit) : Observer<NavigationEvent> { private val executedEvents: HashSet<String> = hashSetOf() /** Clear All Executed Events */ fun clearExecutedEvents() = executedEvents.clear() override fun onChanged(it: NavigationEvent?) { when (it?.type) { Type.EXECUTE_WITHOUT_LIMITS, Type.WAIT_OBSERVER_IF_NEEDED -> { if (!it.isHandled) { it.isHandled = true it.apply(handlerBlock) } } Type.EXECUTE_ONCE, Type.WAIT_OBSERVER_IF_NEEDED_AND_EXECUTE_ONCE -> { if (it.javaClass.simpleName !in executedEvents) { if (!it.isHandled) { it.isHandled = true executedEvents.add(it.javaClass.simpleName) it.apply(handlerBlock) } } } } } } 

рдпрд╣ рдСрдмреНрдЬрд░реНрд╡рд░ рдПрдХ рдЙрдЪреНрдЪ-рдХреНрд░рдо рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдПрдХ рдЗрдирдкреБрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ - рдШрдЯрдирд╛ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдПрдХ рдЯреБрдХрдбрд╝рд╛ (рдиреАрдЪреЗ рдЙрджрд╛рд╣рд░рдг) рдореЗрдВ рд▓рд┐рдЦрд╛ рдЬрд╛рдПрдЧрд╛ред

clearExecutedEvents() рд╡рд┐рдзрд┐ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдШрдЯрдирд╛рдУрдВ рдХреА рд╕рдлрд╛рдИ рдХреЗ рд▓рд┐рдП рд╡рд┐рдзрд┐ (рд╡реЗ рдЬрд┐рдиреНрд╣реЗрдВ рдПрдХ рдмрд╛рд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП)ред рд╕реНрдХреНрд░реАрди рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддреЗ рд╕рдордп рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, swipeToRefresh() ред

рдЦреИрд░, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдореБрдЦреНрдп onChange() рд╡рд┐рдзрд┐, рдЬреЛ рддрдм рд╣реЛрддреА рд╣реИ рдЬрдм рдирдпрд╛ рдПрдорд┐рдЯрд░ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдпрд╣ рдкрд░реНрдпрд╡реЗрдХреНрд╖рдХ рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрддрд╛ рд╣реИред

рдпрджрд┐ рдШрдЯрдирд╛ рдореЗрдВ рдХрдИ рдмрд╛рд░ рдЕрд╕реАрдорд┐рдд рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрди рдкреНрд░рдХрд╛рд░ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЬрд╛рдВрдЪрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рдШрдЯрдирд╛ рдХреЛ рдЕрдВрдЬрд╛рдо рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░реЗрдВред рд╣рдо рдШрдЯрдирд╛ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдкреНрд░рд╛рдкреНрдд рдФрд░ рд╕рдВрд╕рд╛рдзрд┐рдд рд╣реИред

 if (!it.isHandled) { it.isHandled = true it.apply(handlerBlock) } 

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

 if (it.javaClass.simpleName !in executedEvents) { if (!it.isHandled) { it.isHandled = true executedEvents.add(it.javaClass.simpleName) it.apply(handlerBlock) } } 

рд▓реЗрдХрд┐рди рдШрдЯрдирд╛рдУрдВ рдХреЗ рдЕрдВрджрд░ рдбреЗрдЯрд╛ рдХреИрд╕реЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВ?


рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, MyFragmentNavigation рдЗрдВрдЯрд░рдлрд╝реЗрд╕ MyFragmentNavigation , рдЬрд┐рд╕рдореЗрдВ NavigationEvent() рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓реА рдХрдХреНрд╖рд╛рдПрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛрдВрдЧреАред рдЙрддреНрддреАрд░реНрдг рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдФрд░ рдмрд┐рдирд╛ рд╡рд┐рднрд┐рдиреНрди рдХрдХреНрд╖рд╛рдПрдВ рдиреАрдЪреЗ рдмрдирд╛рдИ рдЧрдИ рд╣реИрдВред

 interface MyFragmentNavigation { class ShowCategoryList : NavigationEvent() class OpenProduct(val productId: String, val productName: String) : NavigationEvent() class PlayVideo(val url: String) : NavigationEvent() class ShowNetworkError : NavigationEvent() } 

рдпрд╣ рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ


ViewModel рд╕реЗ рдШрдЯрдирд╛рдПрдБ рднреЗрдЬрдирд╛:

 class MyViewModel : ViewModel() { val emitter = Events.Enitter() fun doOnShowCategoryListButtonClicked() = emitter.emitAndExecute(MyNavigation.ShowCategoryList()) fun doOnPlayClicked() = emitter.waitAndExecuteOnce(MyNavigation.PlayVideo(url = "https://site.com/abc")) fun doOnProductClicked() = emitter.emitAndExecute(MyNavigation.OpenProduct( productId = "123", productTitle = " Samsung") ) fun doOnNetworkError() = emitter.emitAndExecuteOnce(MyNavigation.ShowNetworkError()) fun doOnSwipeRefresh(){ emitter.clearWaitingEvents() ..//loadData() } } 

рдПрдХ рдЯреБрдХрдбрд╝реЗ рдореЗрдВ рдШрдЯрдирд╛рдПрдБ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛:

 class MyFragment : Fragment() { private val navigationEventsObserver = Events.EventObserver { event -> when (event) { is MyFragmentNavigation.ShowCategoryList -> ShowCategoryList() is MyFragmentNavigation.PlayVideo -> videoPlayerView.loadUrl(event.url) is MyFragmentNavigation.OpenProduct -> openProduct(id = event.productId, name = event.otherInfo) is MyFragmentNavigation.ShowNetworkError -> showNetworkErrorAlert() } } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // Observer   ViewModels     myViewModel.emitter.observe(viewLifecycleOwner, navigationEventsObserver) myViewModelSecond.emitter.observe(viewLifecycleOwner, navigationEventsObserver) myViewModelThird.emitter.observe(viewLifecycleOwner, navigationEventsObserver) } private fun ShowCategoryList(){ ... } private fun openProduct(id: String, name: String){ ... } private fun showNetworkErrorAlert(){ ... } } 

рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рд╣рдореЗрдВ Rx- BehaviorSubjec ta рдФрд░ EventBus -a рдХрд╛ рдПрдХ рдПрдирд╛рд▓реЙрдЧ рдорд┐рд▓рд╛ рд╣реИ, рдЬреЛ рдХреЗрд╡рд▓ LiveData рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ, рдЬрд┐рд╕рдореЗрдВ Emitter рдСрдмреНрдЬрд░реНрд╡рд░ рдирд┐рд╖реНрдкрд╛рджрдХ рдХреЗ рд╕рд╛рдордиреЗ рдЖрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдШрдЯрдирд╛рдУрдВ рдХреЛ рдПрдХрддреНрд░ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдЬрд┐рд╕рдореЗрдВ рдСрдмреНрдЬрд░реНрд╡рд░ рдЗрд╡реЗрдВрдЯ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рддреЛ рдЙрдиреНрд╣реЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдХреЙрд▓ рдХрд░реЗрдВред

рд╕реБрдЭрд╛рд╡реЛрдВ рдХреЗ рд╕рд╛рде рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИред

рд╕реНрд░реЛрдд рд╕реЗ рд▓рд┐рдВрдХ рдХрд░реЗрдВ
рд╣реЛрдо рдХреНрд░реЗрдбрд┐рдЯ рдмреИрдВрдХ рд╕реЗ рдХрд┐рд╕реНрдд рдпреЛрдЬрдирд╛ ред

Source: https://habr.com/ru/post/hi477314/


All Articles