RxJava2 + Retrofit 2. рд╣рдо рдПрдВрдбреНрд░реЙрдЗрдб рдкрд░ рдЗрдВрдЯрд░рдиреЗрдЯ рдХреА рд╕реНрдерд┐рддрд┐ рдХреА рдХрдореА рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдбрд╛рдкреНрдЯрд░ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рддреЗ рд╣реИрдВ



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

рдХреНрдпрд╛ рдЗрд╕ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реИ?


рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, RxJava2 рдФрд░ Retrofit2 рдЗрд╕реЗ рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВред

Stackoverflow рдкрд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрдИ рд╕рдорд╛рдзрд╛рди рд╣реИрдВ:

1. рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ CallAdapterFactory рдмрдирд╛рдирд╛ (рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдпрд╣рд╛рдБ )
2. рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░реЗрдВ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░реЗрдВрд╕рдмрдЬреЗрдХреНрдЯ (рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдпрд╣рд╛рдВ )

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

рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди


рдЪрд▓реЛ рдПрдХ рд╕рд░рд▓ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рддреЗ рд╣реИрдВред рдореБрдЦреНрдп рд╕реНрдХреНрд░реАрди рдкрд░ рджреЛ рдЯреИрдм рд░рдЦреЗрдВред рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдкрд╛рда рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬреЛ рджрд┐рдЦрд╛рдПрдЧрд╛ рдХрд┐ рдХрд┐рддрдиреЗ рддрддреНрд╡ рдПрдкреАрдЖрдИ рджреНрд╡рд╛рд░рд╛ рд▓реЛрдб рдХрд┐рдП рдЧрдП рд╣реИрдВред рдпрджрд┐ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рджреМрд░рд╛рди рдХреЛрдИ рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИ, рддреЛ рд╣рдо рдПрдХ SnackBar рдХреЛ Try Again рдмрдЯрди рдХреЗ рд╕рд╛рде рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВред



рд╣рдо рдРрд╕реЗ рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рдХреЛ рдмреЗрд╕рдПрдХреНрдЯрд┐рд╡рд┐рдЯреА, рдмреЗрд╕рдЧреНрд░реИрдЧрдореЗрдВрдЯ, рдмреЗрд╕ рд╡реНрдпреВрдореЙрдбрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рд╡реЗ рдПрдХ рд╕реНрдерд╛рди рдкрд░ рдЕрдиреБрд░реЛрдз рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреЗ рддрд░реНрдХ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдФрд░ рдЗрд╕ рдХреЛрдб рдХреЗ рджреЛрд╣рд░рд╛рд╡ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИрдВред BaseFragment рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рджреЛ рдЯреБрдХрдбрд╝реЗ рдмрдирд╛рдПрдБред рдкреНрд░рддреНрдпреЗрдХ рд░рдЦреЗ рд╣реБрдП рдЯреБрдХрдбрд╝реЗ рдХрд╛ рдЕрдкрдирд╛ ViewModel рд╣реИ рдФрд░ рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рдПрдкреАрдЖрдИ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдХрд░рддрд╛ рд╣реИред рдореИрдВрдиреЗ рдЗрди рд╕реНрдирд┐рдкреЗрдЯ рдХреЛ рдпрд╣ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдпрд╛ рдХрд┐ рдпрджрд┐ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИ, рддреЛ рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рджреЛрд╣рд░рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕рдХреЗ рдмрд╛рдж, рдПрдХ RxRetryCallAdapterFactory рдлреИрдХреНрдЯреНрд░реА рдмрдирд╛рдПрдВ рдЬреЛ CallAdapter.Factory рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рддрд╛ рд╣реИред рдЙрд╕рдХреЗ рдмрд╛рдж, RxJava2CallAdapterFactory рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдПрдВред рд╣рдореЗрдВ RxJava2CallAdapter рдХреЛ рдПрдХреНрд╕реЗрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдЙрд╕ рдХреЛрдб рдХреЛ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд░реЗрдЯреНрд░реЛрдлрд┐рдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдЗрдП рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдмрдирд╛рдПрдВ рдЬреЛ рд╣рдорд╛рд░реЗ рдХрд╛рд░рдЦрд╛рдиреЗ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреЗрдЧрд╛ред рдиреАрдЪреЗ рдирдореВрдирд╛ рдХреЛрдб:

class RxRetryCallAdapterFactory : CallAdapter.Factory() { companion object { fun create() : CallAdapter.Factory = RxRetryCallAdapterFactory() } private val originalFactory = RxJava2CallAdapterFactory.create() override fun get(returnType : Type, annotations : Array<Annotation>, retrofit : Retrofit) : CallAdapter<*, *>? { val adapter = originalFactory.get(returnType, annotations, retrofit) ?: return null return RxRetryCallAdapter(adapter) } } 

рдЗрд╕рдХреЗ рдмрд╛рдж, рдПрдХ RxRetryCallAdapter рдмрдирд╛рдПрдВ рдЬреЛ CallAdapter рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рд╣рдореЗрдВ рдХреЙрд▓ рдПрдбреЙрдкреНрдЯрд░ рдЙрджрд╛рд╣рд░рдг рдХреЛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЗ рдкрд╛рд╕ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ RxJava2CallAdapter рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬреЛ рдореВрд▓ рдХрд╛рд░рдЦрд╛рдирд╛ рд▓реМрдЯрд╛рддрд╛ рд╣реИред

рдЕрдЧрд▓рд╛, рд╣рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЪреАрдЬреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

  • рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд░рд┐рдЯреНрд░реАрд╡реЗрди рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ
  • doOnError () рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдЬреЛ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╣реИрдВрдбрд▓ рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдкреНрд░рд╕рд╛рд░рдг рдХреЛ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдХрд┐ рдмреЗрд╕рдПрдХреНрдЯрд┐рд╡рд┐рдЯреА рдореЗрдВ рд╕рдВрд╕рд╛рдзрд┐рдд рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рд╕реНрдиреИрдХрдмрд╛рд░ рджрд┐рдЦрд╛рддрд╛ рд╣реИред
  • рдкрдмреНрд▓рд┐рд╢рд╕рдмрдЬреЗрдХреНрдЯ рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдПрдХ рдЗрд╡реЗрдВрдЯ рдЯреНрд░рд┐рдЧрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдЪреЗрди рдкрд░ рдлрд┐рд░ рд╕реЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХрд░рддрд╛ рд╣реИред
  • рдЕрд╡рд▓реЛрдХрди рдХрд░реЗрдВ (Schedulers.io ()) рдСрдкрд░реЗрдЯрд░ рдЬрд┐рд╕реЗ рдкрдмреНрд▓рд┐рд╢рд╕рдмрдЬреЗрдХреНрдЯ рдкрд░ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП (рдпрджрд┐ рдпрд╣ рд▓рд╛рдЗрди рдирд╣реАрдВ рдЬреЛрдбрд╝реА рдЧрдИ рд╣реИ, рддреЛ рд╕рджрд╕реНрдпрддрд╛ рдореБрдЦреНрдп рдереНрд░реЗрдб рдореЗрдВ рд╣реЛрдЧреА рдФрд░ рд╣рдореЗрдВ NetworkOnMainThreadException рдорд┐рд▓ рдЬрд╛рдПрдЧреА
  • рд╣рдо PublishSubject рдХреЛ Flowable рдореЗрдВ рдмрджрд▓рддреЗ рд╣реИрдВ рдФрд░ BackpressureStrategy.LATEST рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдЕрдВрддрд┐рдо рддреНрд░реБрдЯрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ

рдиреЛрдЯ: PublishSubject рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд╕рд┐рдВрдЧрд▓рдЯрди рдХреНрд▓рд╛рд╕ рдмрдирд╛рдпрд╛, рдЬреЛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд╕рднреА рд╕рд┐рдВрдЧрд▓рдЯрди рдирд┐рд░реНрднрд░рддрд╛ рдХреЛ рдЙрдЬрд╛рдЧрд░ рдХрд░рддрд╛ рд╣реИред рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ, рдЖрдк рдбреИрдЧрд░ 2 рдЬреИрд╕реА рдирд┐рд░реНрднрд░рддрд╛ рдЗрдВрдЬреЗрдХреНрд╢рди рдврд╛рдВрдЪреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд░рдЦрддреЗ рд╣реИрдВ

 class RxRetryCallAdapter<R>(private val originalAdapter : CallAdapter<R, *>) : CallAdapter<R, Any> { override fun adapt(call : Call<R>) : Any { val adaptedValue = originalAdapter.adapt(call) return when (adaptedValue) { is Completable -> { adaptedValue.doOnError(this::sendBroadcast) .retryWhen { AppProvider.provideRetrySubject().toFlowable(BackpressureStrategy.LATEST) .observeOn(Schedulers.io()) } } is Single<*> -> { adaptedValue.doOnError(this::sendBroadcast) .retryWhen { AppProvider.provideRetrySubject().toFlowable(BackpressureStrategy.LATEST) .observeOn(Schedulers.io()) } } //same for Maybe, Observable, Flowable else -> { adaptedValue } } } override fun responseType() : Type = originalAdapter.responseType() private fun sendBroadcast(throwable : Throwable) { Timber.e(throwable) LocalBroadcastManager.getInstance(AppProvider.appInstance).sendBroadcast(Intent(BaseActivity.ERROR_ACTION)) } } 

рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддрд╛ рд╣реИ, рд╣рдо onNext PublishSubject рдкрд░ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВред рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рдЖрд░рдПрдХреНрд╕ рдЪреЗрди рдХреА рдлрд┐рд░ рд╕реЗ рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрддреЗ рд╣реИрдВред

рдкрд░реАрдХреНрд╖рдг


рдЗрдВрдЯрд░рдиреЗрдЯ рдмрдВрдж рдХрд░реЗрдВ рдФрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЪрд▓рд╛рдПрдВред рдкреНрд░рддреНрдпреЗрдХ рдЯреИрдм рдкрд░ рд▓реЛрдб рдХреА рдЧрдИ рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╢реВрдиреНрдп рд╣реИ рдФрд░ рд╕реНрдиреИрдХрдмрд╛рд░ рдПрдХ рддреНрд░реБрдЯрд┐ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЗрдВрдЯрд░рдиреЗрдЯ рдЪрд╛рд▓реВ рдХрд░реЗрдВ рдФрд░ рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВред рдХреБрдЫ рд╕реЗрдХрдВрдб рдХреЗ рдмрд╛рдж, рдкреНрд░рддреНрдпреЗрдХ рдЯреИрдм рдкрд░ рд▓реЛрдб рдХреА рдЧрдИ рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдмрджрд▓ рдЬрд╛рддреА рд╣реИред



рдЕрдЧрд░ рдХрд┐рд╕реА рдХреЛ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рд╕реНрд░реЛрдд рдХреЛрдб рдпрд╣рд╛рдВ рд╣реИ

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


All Articles