
рдирдорд╕реНрдХрд╛рд░, рд╣реЗрдмреНрд░!
рдореЗрд░рд╛ рдирд╛рдо рдПрд░реНрдЯреЛрдо рдбреЛрдмреНрд░реЛрд╡рд┐рдВрд╕реНрдХреА рд╣реИ, рдореИрдВ
рдлрд┐рдВрдЪ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реВрдВред рдореЗрд░рд╛ рд╕реБрдЭрд╛рд╡ рд╣реИ рдХрд┐ рдХреИрд╕реЗ рдмрд╣реБрд░рдВрдЧреА рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП
Arrow
рдлрдВрдХреНрд╢рдирд▓ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рдкрд┐рддрд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдиреЗ рдПрдХ рд▓реЗрдЦ рдкрдврд╝рд╛ред рдЕрдХреНрд╕рд░ рдЬреЛ рд▓реЛрдЧ рдХреЗрд╡рд▓ рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╢реИрд▓реА рдореЗрдВ рд▓рд┐рдЦрдирд╛ рд╢реБрд░реВ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд╡реЗ рдкреБрд░рд╛рдиреА рдЖрджрддреЛрдВ рдХреЗ рд╕рд╛рде рднрд╛рдЧ рд▓реЗрдиреЗ рдХреА рдЬрд▓реНрджреА рдореЗрдВ рдирд╣реАрдВ рд╣реИрдВ, рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдбреАрдЖрдИ рдХрдВрдЯреЗрдирд░ рдФрд░ рд╡рд┐рд░рд╛рд╕рдд рдХреЗ рд╕рд╛рде рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдЕрдирд┐рд╡рд╛рд░реНрдпрддрд╛ рд▓рд┐рдЦрддреЗ рд╣реИрдВред рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рд╡рд┐рдЪрд╛рд░ рдХрдИ рд▓реЛрдЧреЛрдВ рдХреЛ рд╕рд╣реА рджрд┐рд╢рд╛ рдореЗрдВ рд╕реЛрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЗрд░рд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИред
рдХрд╛ рдЖрдирдВрдж рд▓реЗрдВ!
***
рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рд╣рдо рд░рдирдЯрд╛рдЗрдо рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдбреЗрдЯрд╛ рдХреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪреЗ рдмрд┐рдирд╛ рдЖрд╡реЗрджрди рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдмрд╕ рдпрд╣ рд╡рд░реНрдгрди рдХрд░реЗрдВ рдХрд┐ рдЗрд╕ рдбреЗрдЯрд╛ рдХреЛ рдХреИрд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛?
рдХрд▓реНрдкрдирд╛ рдХреАрдЬрд┐рдП рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╣реИ рдЬреЛ RxJava рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ рдСрдмреНрдЬрд░реНрд╡реЗрдмрд▓ рдЯрд╛рдЗрдк рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдкреНрд░рдХрд╛рд░ рд╣рдореЗрдВ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХреЙрд▓ рдФрд░ рдореИрдирд┐рдкреБрд▓реЗрд╢рди рдХреА рд╢реНрд░реГрдВрдЦрд▓рд╛ рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдВрдд рдореЗрдВ, рдХреНрдпрд╛ рдпрд╣ Observable
рдХреЗрд╡рд▓ рдЕрддрд┐рд░рд┐рдХреНрдд рдЧреБрдгреЛрдВ рд╡рд╛рд▓рд╛ рдХрдВрдЯреЗрдирд░ рдирд╣реАрдВ рд╣реЛрдЧрд╛?
Flowable
, Flowable
( Flowable
), Future
, IO
рдФрд░ рдХрдИ рдЕрдиреНрдп рдЬреИрд╕реЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╣реА рдХрд╣рд╛рдиреАред
рд╡реИрдЪрд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ, рдпреЗ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдПрдХ рдСрдкрд░реЗрд╢рди рд╣реИ (рднрд╡рд┐рд╖реНрдп рдореЗрдВ рд▓рд╛рдЧреВ рд╣реЛрдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛рдИ рдпрд╛ рдмрдирд╛рдИ рдЧрдИ рд╣реИ) рдЬреЛ рдПрдХ рджреВрд╕рд░реЗ рдкреНрд░рдХрд╛рд░ ( map
) рдХреЗ рд▓рд┐рдП рдЖрдВрддрд░рд┐рдХ рдореВрд▓реНрдп рдХреЛ рдХрд╛рд╕реНрдЯрд┐рдВрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛрдбрд╝рддреЛрдбрд╝ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдЗрд╕реА рдкреНрд░рдХрд╛рд░ рдХреЗ рдЕрдиреНрдп рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрди рдХрд░рддреЗ рд╣реБрдП рдЗрд╕реА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП flatMap
рдХрд╛ рдЙрдкрдпреЛрдЧ flatMap
( zip
), рдЖрджрд┐ред
рдЗрди рд╡реНрдпрд╡рд╣рд╛рд░реЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдШреЛрд╖рдгрд╛рддреНрдордХ рд╡рд┐рд╡рд░рдг рдмрдирд╛рдП рд░рдЦрддреЗ рд╣реБрдП, рдФрд░ рдЖрдкрдХреЗ рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдХреЛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдЬреИрд╕реЗ рдХрд┐ flatMap
рд╕реНрд╡рддрдВрддреНрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП Observable
рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ рдХрд┐ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХреБрдЫ рдЕрдиреБрдмрдВрдзреЛрдВ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реЛрддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ рдХрд┐ map
, flatMap
рдФрд░ рдЕрдиреНрдпред ред
рдРрд╕рд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЕрдЬреАрдм рдпрд╛ рдмрд╣реБрдд рдЬрдЯрд┐рд▓ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рджрд┐рд▓рдЪрд╕реНрдк рдлрд╛рдпрджреЗ рд╣реИрдВред рдкрд╣рд▓реЗ, рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ, рдФрд░ рдлрд┐рд░ рдЙрдирдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВред
рд╡рд┐рд╣рд┐рдд рд╕рдорд╕реНрдпрд╛
рдорд╛рди рд▓реАрдЬрд┐рдП рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдЯреВ-рдбреВ рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдПрдХ рдЖрд╡реЗрджрди рд╣реИ, рдФрд░ рд╣рдо рд╕реНрдерд╛рдиреАрдп рдХреИрд╢ рд╕реЗ рдЯрд╛рдЗрдк Task
рдХреА рд╡рд╕реНрддреБрдУрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдирд┐рдХрд╛рд▓рдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗред рдпрджрд┐ рд╡реЗ рд╕реНрдерд╛рдиреАрдп рд╕рдВрдЧреНрд░рд╣рдг рдореЗрдВ рдирд╣реАрдВ рдкрд╛рдП рдЬрд╛рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдЙрдиреНрд╣реЗрдВ рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рдХреНрд╡реЗрд░реА рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВрдЧреЗред рд╣рдореЗрдВ рджреЛрдиреЛрдВ рдбреЗрдЯрд╛ рд╕реНрд░реЛрддреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдХрд▓ рдЕрдиреБрдмрдВрдз рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рджреЛрдиреЛрдВ рдХреЛ рд╕реНрд░реЛрдд рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ рдЙрдкрдпреБрдХреНрдд User
рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдЯрд╛рдЗрдк Task
рдХреА рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕реВрдЪреА рдорд┐рд▓ рд╕рдХреЗ:
interface DataSource { fun allTasksByUser(user: User): Observable<List<Task>> }
рдпрд╣рд╛рдБ, рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рд╣рдо Flowable
, рд▓реЗрдХрд┐рди рдпрд╣ Single
, Maybe
, Flowable
, Deferred
- рд▓рдХреНрд╖реНрдп рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рд╣реЛред
рдбреЗрдЯрд╛ рд╕реНрд░реЛрддреЛрдВ рдХреЗ рдореЛрдЪрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдПрдХ рдЬреЛрдбрд╝реЗ рдХреЛ рдЬреЛрдбрд╝реЗрдВ, рдПрдХ
рдФрд░ рдПрдХ
ред
class LocalDataSource : DataSource { private val localCache: Map<User, List<Task>> = mapOf(User(UserId("user1")) to listOf(Task("LocalTask assigned to user1"))) override fun allTasksByUser(user: User): Observable<List<Task>> = Observable.create { emitter -> val cachedUser = localCache[user] if (cachedUser != null) { emitter.onNext(cachedUser) } else { emitter.onError(UserNotInLocalStorage(user)) } } } class RemoteDataSource : DataSource { private val internetStorage: Map<User, List<Task>> = mapOf(User(UserId("user2")) to listOf(Task("Remote Task assigned to user2"))) override fun allTasksByUser(user: User): Observable<List<Task>> = Observable.create { emitter -> val networkUser = internetStorage[user] if (networkUser != null) { emitter.onNext(networkUser) } else { emitter.onError(UserNotInRemoteStorage(user)) } } }
рджреЛрдиреЛрдВ рдбреЗрдЯрд╛ рд╕реНрд░реЛрддреЛрдВ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓рдЧрднрдЧ рд╕рдорд╛рди рд╣реИред рдпреЗ рдЗрди рд╕реНрд░реЛрддреЛрдВ рдХреЗ рдХреЗрд╡рд▓ рдирдХрд▓реА рд╕рдВрд╕реНрдХрд░рдг рд╣реИрдВ рдЬреЛ рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ рд╕реНрдерд╛рдиреАрдп рднрдВрдбрд╛рд░рдг рдпрд╛ рдиреЗрдЯрд╡рд░реНрдХ рдПрдкреАрдЖрдИ рд╕реЗ рдбреЗрдЯрд╛ рдЦреАрдВрдЪрддреЗ рд╣реИрдВред рджреЛрдиреЛрдВ рд╣реА рдорд╛рдорд▓реЛрдВ рдореЗрдВ, Map<User, List<Task>>
рдХрд╛ рдЙрдкрдпреЛрдЧ рдбреЗрдЯрд╛ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдХреНрдпреЛрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдбреЗрдЯрд╛ рдХреЗ рджреЛ рд╕реНрд░реЛрдд рд╣реИрдВ, рд╣рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рдХрд┐рд╕реА рддрд░рд╣ рд╕рдордиреНрд╡рдпрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдПрдХ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдмрдирд╛рдПрдБ:
class TaskRepository(private val localDS: DataSource, private val remoteDS: RemoteDataSource) { fun allTasksByUser(user: User): Observable<List<Task>> = localDS.allTasksByUser(user) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.computation()) .onErrorResumeNext { _: Throwable -> remoteDS.allTasksByUser(user) } }
рдпрд╣ рдХреЗрд╡рд▓ LocalDataSource
рд╕реЗ List<Task>
рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рдпрд╣ рдирд╣реАрдВ рдкрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ LocalDataSource
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЙрдиреНрд╣реЗрдВ рдиреЗрдЯрд╡рд░реНрдХ рд╕реЗ рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИред
рдЪрд▓реЛ рдирд┐рд░реНрднрд░рддрд╛ рдЗрдВрдЬреЗрдХреНрд╢рди (DI) рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рднреА рдврд╛рдВрдЪреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛ рдирд┐рд░реНрднрд░рддрд╛ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рдореЙрдбреНрдпреВрд▓ рдмрдирд╛рдПрдБ:
class Module { private val localDataSource: LocalDataSource = LocalDataSource() private val remoteDataSource: RemoteDataSource = RemoteDataSource() val repository: TaskRepository = TaskRepository(localDataSource, remoteDataSource) }
рдФрд░ рдЕрдВрдд рдореЗрдВ, рд╣рдореЗрдВ рдПрдХ рд╕рд░рд▓ рдкрд░реАрдХреНрд╖рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬреЛ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдкреВрд░реЗ рдвреЗрд░ рдХреЛ рдЪрд▓рд╛рддрд╛ рд╣реИ:
object test { @JvmStatic fun main(args: Array<String>): Unit { val user1 = User(UserId("user1")) val user2 = User(UserId("user2")) val user3 = User(UserId("unknown user")) val dependenciesModule = Module() dependenciesModule.run { repository.allTasksByUser(user1).subscribe({ println(it) }, { println(it) }) repository.allTasksByUser(user2).subscribe({ println(it) }, { println(it) }) repository.allTasksByUser(user3).subscribe({ println(it) }, { println(it) }) } } }
рдЙрдкрд░реЛрдХреНрдд рд╕рднреА рдХреЛрдб рдЬреАрдердм рдкрд░ рдкрд╛рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ ред
рдпрд╣ рдХрд╛рд░реНрдпрдХреНрд░рдо рддреАрди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдирд┐рд╖реНрдкрд╛рджрди рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреА рд░рдЪрдирд╛ рдХрд░рддрд╛ рд╣реИ, рдлрд┐рд░ рдкрд░рд┐рдгрд╛рдореА Observable
рд▓рд┐рдП рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрддрд╛ рд╣реИред
User
рдкрд╣рд▓реЗ рджреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдЙрдкрд▓рдмреНрдз рд╣реИрдВ, рдЗрд╕рдХреЗ рд╕рд╛рде рд╣рдо рднрд╛рдЧреНрдпрд╢рд╛рд▓реА рдереЗред User1
рд╕реНрдерд╛рдиреАрдп DataSource
рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИ, рдФрд░ User2
рд░рд┐рдореЛрдЯ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИред
рд▓реЗрдХрд┐рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ 3 рдХреЗ рд╕рд╛рде рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕реНрдерд╛рдиреАрдп рднрдВрдбрд╛рд░рдг рдореЗрдВ рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реИред рдХрд╛рд░реНрдпрдХреНрд░рдо рдЗрд╕реЗ рджреВрд░рд╕реНрде рд╕реЗрд╡рд╛ рд╕реЗ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдЧрд╛ - рд▓реЗрдХрд┐рди рдпрд╣ рд╡рд╣рд╛рдВ рднреА рдирд╣реАрдВ рд╣реИред рдЦреЛрдЬ рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рдПрдЧреА, рдФрд░ рд╣рдо рдХрдВрд╕реЛрд▓ рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдВрдЧреЗред
рдпрд╣рд╛рдБ рддреАрдиреЛрдВ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдХрдВрд╕реЛрд▓ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛:
> [Task(value=LocalTask assigned to user1)] > [Task(value=Remote Task assigned to user2)] > UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user)))
рд╣рдо рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЕрдм рдЗрд╕ рддрд░реНрдХ рдХреЛ
рдХреА рд╢реИрд▓реА рдореЗрдВ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред
рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдЕрдореВрд░реНрдд
рдЕрдм DataSource
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рдЕрдиреБрдмрдВрдз рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛:
interface DataSource<F> { fun allTasksByUser(user: User): Kind<F, List<Task>> }
рд╕рдм рдХреБрдЫ рд╕рдорд╛рди рд▓рдЧрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рджреЛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЕрдВрддрд░ рд╣реИрдВ:
- рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдкреНрд░рдХрд╛рд░ (рдЬреЗрдиреЗрд░рд┐рдХ)
F
рдкрд░ рдирд┐рд░реНрднрд░рддрд╛ рд╣реИ F
- рдлрд╝рдВрдХреНрд╢рди рджреНрд╡рд╛рд░рд╛ рд▓реМрдЯрд╛рдпрд╛ рдЧрдпрд╛ рдкреНрд░рдХрд╛рд░ рдЕрдм
Kind<F, List<Task>>
ред
Kind
рдПрд░реЛ рдХреЛ рдХрд┐рд╕ Kind
рд╕реЗ рдПрдирдХреЛрдб рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдЖрдорддреМрд░ рдкрд░ рдПрдХ (higher kind)
рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ
рдореИрдВ рдЗрд╕ рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЛ рдПрдХ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рд╕рдордЭрд╛рдКрдВрдЧрд╛ред
Observable<A>
рдХреЗ 2 рднрд╛рдЧ рд╣реИрдВ:
Observable
: рдХрдВрдЯреЗрдирд░, рдирд┐рд╢реНрдЪрд┐рдд рдкреНрд░рдХрд╛рд░редA
: рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рдХрд╛ рддрд░реНрдХред рдПрдХ рдЕрдореВрд░реНрдд рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░ рдкрд╛рд░рд┐рдд рдХрд┐рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред
рд╣рдо A
рдЬреИрд╕реЗ рд╕рд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рд▓реЗрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдмрд╣реБрдд рд╕реЗ рд▓реЛрдЧ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо Observable
рдХрдВрдЯреЗрдирд░ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рднреА рдкрд╛рд▓рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдХреЗ рд▓рд┐рдП, рдЙрдЪреНрдЪ рдкреНрд░рдХрд╛рд░ рд╣реИрдВред
рд╡рд┐рдЪрд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ F<A>
рдЬреИрд╕рд╛ рдПрдХ рдирд┐рд░реНрдорд╛рддрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ F
рдФрд░ A
рджреЛрдиреЛрдВ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдЕрднреА рддрдХ рдХреЛрдЯрд▓рд┐рди рдХрдВрдкрд╛рдЗрд▓рд░ ( рдЕрднреА рднреА? ) рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕реЗ рдПрдХ рд╕рдорд╛рди рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде рдирдХрд▓ рдХрд░реЗрдВрдЧреЗред
рдПрд░реЛ рдПрдХ рдЗрдВрдЯрд░рдореАрдбрд┐рдПрдЯ рдореЗрдЯрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ Kind<F, A>
рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рджреЛрдиреЛрдВ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдВрдХ рд╣реЛрддреЗ рд╣реИрдВ, рдФрд░ рд╕рдВрдХрд▓рди рдХреЗ рджреМрд░рд╛рди рджреЛрдиреЛрдВ рджрд┐рд╢рд╛рдУрдВ рдореЗрдВ рдХрдиреНрд╡рд░реНрдЯрд░реНрд╕ рднреА рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ рддрд╛рдХрд┐ рдЖрдк Kind<Observable, List<Task>>
рд╕реЗ рдкрде рдХрд╛ рдЕрдиреБрд╕рд░рдг рдХрд░ рд╕рдХреЗрдВред Kind<Observable, List<Task>>
Observable<List<Task>>
рдФрд░ рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрддред рдПрдХ рдЖрджрд░реНрд╢ рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИред
рддреЛ рдлрд┐рд░, рд╣рдорд╛рд░реЗ рднрдВрдбрд╛рд░ рдХрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рджреЗрдЦреЗрдВ:
interface DataSource<F> { fun allTasksByUser(user: User): Kind<F, List<Task>> }
DataSource
рдлрд╝рдВрдХреНрд╢рди рдЙрдЪреНрдЪ рдкреНрд░рдХрд╛рд░ рджреЗрддрд╛ рд╣реИ: Kind<F, List<Task>>
ред рдпрд╣ F<List<Task>>
, рдЬрд╣рд╛рдВ F
рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рд░рд╣рддрд╛ рд╣реИред
рд╣рдо рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдореЗрдВ рдХреЗрд╡рд▓ List<Task>
рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░рддреЗ рд╣реИрдВред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рд╣рдо рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ F
рдХрдВрдЯреЗрдирд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрдм рддрдХ рдХрд┐ рдЗрд╕рдореЗрдВ рдПрдХ List<Task>
ред рд╣рдо рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рдбреЗрдЯрд╛ рдХрдВрдЯреЗрдирд░ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕реНрдкрд╖реНрдЯ рд╣реИ? рдЖрдЧреЗ рдмрдврд╝реЛред
рдЖрдЗрдП рдЗрд╕ рддрд░рд╣ рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдП рдЧрдП DataSource
рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ, рд▓реЗрдХрд┐рди рдЗрд╕ рдмрд╛рд░ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд▓рд┐рдП рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рд╕реНрдерд╛рдиреАрдп:
class LocalDataSource<F>(A: ApplicativeError<F, Throwable>) : DataSource<F>, ApplicativeError<F, Throwable> by A { private val localCache: Map<User, List<Task>> = mapOf(User(UserId("user1")) to listOf(Task("LocalTask assigned to user1"))) override fun allTasksByUser(user: User): Kind<F, List<Task>> = Option.fromNullable(localCache[user]).fold( { raiseError(UserNotInLocalStorage(user)) }, { just(it) } ) }
рдмрд╣реБрдд рд╕реА рдирдИ рдЪреАрдЬреЛрдВ рдХреЛ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИ, рд╣рдо рд╣рд░ рдЪреАрдЬ рдХрд╛ рдЪрд░рдг рджрд░ рдЪрд░рдг рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВрдЧреЗред
рдпрд╣ DataSource
рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ F
рдмрдирд╛рдП рд░рдЦрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ DataSource<F>
рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред рд╣рдо рдмрд╛рд╣рд░ рд╕реЗ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреНрд░рд╕рд╛рд░рдг рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд░рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред
рдЕрдм, рдирд┐рд░реНрдорд╛рддрд╛ рдореЗрдВ рд╕рдВрднрд╡рддрдГ рдЕрдкрд░рд┐рдЪрд┐рдд allTasksByUser()
рдмрд╛рд░реЗ рдореЗрдВ рднреВрд▓ рдЬрд╛рдПрдВ рдФрд░ allTasksByUser()
рдлрд╝рдВрдХреНрд╢рди рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░реЗрдВред рдФрд░ рд╣рдо рдРрдкреНрд▓реАрдХреЗрд╢рди рдкрд░ рд▓реМрдЯ рдЖрдПрдВрдЧреЗред
override fun allTasksByUser(user: User): Kind<F, List<Task>> = Option.fromNullable(localCache[user]).fold( { raiseError(UserNotInLocalStorage(user)) }, { just(it) } )
рдпрд╣ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ Kind<F, List<Task>>
ред рд╣рдореЗрдВ рдЕрднреА рднреА рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдХрдВрдЯреЗрдирд░ F
рдХреНрдпрд╛ F
рдЬрдм рддрдХ рдХрд┐ рдЗрд╕рдореЗрдВ рдПрдХ List<Task>
ред
рд▓реЗрдХрд┐рди рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИред рдЗрд╕ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддреЗ рд╣реБрдП рдХрд┐ рд╣рдо рд╕реНрдерд╛рдиреАрдп рд╕реНрдЯреЛрд░реЗрдЬ рдореЗрдВ рд╡рд╛рдВрдЫрд┐рдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП Task
рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреА рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдирд╣реАрдВ, рд╣рдо рдПрдХ рддреНрд░реБрдЯрд┐ (рдХреЛрдИ Task
рдирд╣реАрдВ рдорд┐рд▓рд╛) рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдпрд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЯрд╛ рдореЗрдВ рд▓рд┐рдкрдЯреЗ Task
( Task
рдкрд╛рдпрд╛ рдЧрдпрд╛) рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред
рдФрд░ рджреЛрдиреЛрдВ рд╣реА рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд╣рдореЗрдВ рд▓реМрдЯрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: Kind<F, List<Task>>
ред
рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ: рдПрдХ рдкреНрд░рдХрд╛рд░ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо ( F
) рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ, рдФрд░ рд╣рдореЗрдВ рдЙрд╕ рдкреНрд░рдХрд╛рд░ рд╕реЗ рд▓рд┐рдкрдЯреЗ рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд░рд╛рд╕реНрддрд╛ рдЪрд╛рд╣рд┐рдПред рд╕рд╛рде рд╣реА, рд╣рдореЗрдВ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рдЪрд╛рд╣рд┐рдП, рдЬрд┐рд╕рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рдлрд▓ рд╕рдорд╛рдкрди рдХреЗ рдмрд╛рдж рдкреНрд░рд╛рдкреНрдд рдореВрд▓реНрдп рдХреЛ рд▓рдкреЗрдЯрд╛ рдЬрд╛рдПрдЧрд╛ред рдХреБрдЫ рдЕрд╕рдВрднрд╡ рдЬреИрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ?
рдЖрдЗрдП рдХрдХреНрд╖рд╛ рдХреА рдШреЛрд╖рдгрд╛ рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВ рдФрд░ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдПрдкреНрд▓рд┐рдХреЗрдЯрд░ рдХреЛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рдХрдХреНрд╖рд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдХреЗ рд░реВрдк рдореЗрдВ ( by A
) by A
рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
class LocalDataSource<F>(A: ApplicativeError<F, Throwable>) : DataSource<F>, ApplicativeError<F, Throwable> by A {
ApplicativeError
рдПрдкреЗрд░реЗрдЯрд┐рд╡ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд ApplicativeError
рдорд┐рд▓рд╛ рд╣реИ, рджреЛрдиреЛрдВ рд╣реА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╡рд░реНрдЧ рд╣реИрдВред
рдкреНрд░рдХрд╛рд░ рдХрдХреНрд╖рд╛рдПрдВ рд╡реНрдпрд╡рд╣рд╛рд░ (рдЕрдиреБрдмрдВрдз) рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреА рд╣реИрдВред рд╡реЗ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдиреНрдХреЛрдбреЗрдб рд╣реЛрддреЗ рд╣реИрдВ рдЬреЛ рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ Monad<F>
, Functor<F>
рдФрд░ рдХрдИ рдЕрдиреНрдп рдореЗрдВред рдпрд╣ F
рдПрдХ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рд╣реИред рдЗрд╕ рддрд░рд╣, рд╣рдо Either
, Option
, IO
, Flowable
рдФрд░ рдХрдИ рдФрд░ рдЕрдзрд┐рдХ рдкреНрд░рдХрд╛рд░ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЗрд╕рд▓рд┐рдП, рд╣рдорд╛рд░реА рджреЛ рд╕рдорд╕реНрдпрд╛рдУрдВ рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВ:
- рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ
Kind<F, List<Task>>
рдореЗрдВ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдкреНрд░рд╛рдкреНрдд рдорд╛рди рд▓рдкреЗрдЯреЗрдВ
рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдо рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ Applicative
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЪреВрдБрдХрд┐ рдПрдкреНрд▓реАрдХреЗрдЯрд░ рдЗрд╕ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд ApplicativeError
рдорд┐рд▓рд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕рдХреЗ рдЧреБрдгреЛрдВ рдХреЛ рд╕реМрдВрдк рд╕рдХрддреЗ рд╣реИрдВред
Applicative
рд╕рд┐рд░реНрдл just(a)
рдлрд╝рдВрдХреНрд╢рди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред just(a)
рдХрд┐рд╕реА рднреА рдЙрдЪреНрдЪ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдореВрд▓реНрдп рдХреЛ рд▓рдкреЗрдЯрддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдпрджрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ Applicative<F>
, рддреЛ рдХрдВрдЯреЗрдирд░ F
рдореЗрдВ рдореВрд▓реНрдп рдХреЛ рд▓рдкреЗрдЯрдиреЗ рдХреЗ рд▓рд┐рдП just(a)
рдХрд╣ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рднреА рдЙрд╕ рдореВрд▓реНрдп рдХрд╛ рд╣реИред рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдо Observable
рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ Applicative<Observable>
рдЬреЛ рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдПрдХ Observable
рдореЗрдВ рдХреИрд╕реЗ рд▓рдкреЗрдЯреЗрдВ, рддрд╛рдХрд┐ рд╣рдореЗрдВ Observable.just(a)
ред
- рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рддреНрд░реБрдЯрд┐ рд▓рдкреЗрдЯреЗрдВ
Kind<F, List<Task>>
рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдо ApplicativeError
рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдПрдХ рдлрд╝рдВрдХреНрд╢рди raiseError(e)
, рдЬреЛ рдЯрд╛рдЗрдк F
рдХрдВрдЯреЗрдирд░ рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХреЛ рд▓рдкреЗрдЯрддрд╛ рд╣реИ F
Observable
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рддреНрд░реБрдЯрд┐ Observable.error<A>(t)
рддрд░рд╣ рдХреБрдЫ Observable.error<A>(t)
, рдЬрд╣рд╛рдВ t
Throwable
, рдХреНрдпреЛрдВрдХрд┐ рд╣рдордиреЗ рдЕрдкрдиреА рддреНрд░реБрдЯрд┐ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ ApplicativeError<F, Throwable>
рд░реВрдк рдореЗрдВ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рд╣реИ ApplicativeError<F, Throwable>
ред
LocalDataSource<F>
рд╣рдорд╛рд░реЗ рдЕрдореВрд░реНрдд рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред
class LocalDataSource<F>(A: ApplicativeError<F, Throwable>) : DataSource<F>, ApplicativeError<F, Throwable> by A { private val localCache: Map<User, List<Task>> = mapOf(User(UserId("user1")) to listOf(Task("LocalTask assigned to user1"))) override fun allTasksByUser(user: User): Kind<F, List<Task>> = Option.fromNullable(localCache[user]).fold( { raiseError(UserNotInLocalStorage(user)) }, { just(it) } ) }
рд╕реНрдореГрддрд┐ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд Map<User, List<Task>>
рд╕рдорд╛рди рд░рд╣рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдм рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдХреБрдЫ рдРрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдЖрдкрдХреЗ рд▓рд┐рдП рдирдП рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ:
рд╡рд╣ рд╕реНрдерд╛рдиреАрдп рдХреИрд╢ рд╕реЗ Task
рд╕реВрдЪреА рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЪреВрдВрдХрд┐ рд╡рд╛рдкрд╕реА рдореВрд▓реНрдп null
рд╣реЛ рд╕рдХрддрд╛ рд╣реИ ( Task
рдирд╣реАрдВ рдорд┐рд▓ рд╕рдХрддрд╛ рд╣реИ), рд╣рдо Option
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рдореЙрдбрд▓ рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ Option
рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдЙрд╕ рдореВрд▓реНрдп рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдпрд╛ рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ рдЬреЛ рдЗрд╕рдореЗрдВ рд▓рд┐рдкрдЯреЗ рд╣реБрдП рд╣реИрдВред
рд╡реИрдХрд▓реНрдкрд┐рдХ рдореВрд▓реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдЗрд╕рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ fold
рдХрд╣рддреЗ рд╣реИрдВред рдпрд╣ рд╡реИрдХрд▓реНрдкрд┐рдХ рдорд╛рди рдкрд░ when
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИред рдпрджрд┐ рдорд╛рди рдЧрд╛рдпрдм рд╣реИ, рддреЛ Option
рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ F
(рдкрд╣рд▓реЗ рд▓рдВрдмреЛ рдкрд╛рд╕) рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХреЛ рд▓рдкреЗрдЯрддрд╛ рд╣реИред рдФрд░ рдпрджрд┐ рдорд╛рди рдореМрдЬреВрдж рд╣реИ, рддреЛ Option
рдбреЗрдЯрд╛ рдЯрд╛рдЗрдк F
(рджреВрд╕рд░рд╛ рд▓реИрдореНрдмреНрдбрд╛) рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╡рд░рдг рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рддрд╛ рд╣реИред рджреЛрдиреЛрдВ рд╣реА рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдкрд╣рд▓реЗ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА raiseError()
рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: raiseError()
рдФрд░ just()
ред
рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдордиреЗ рдХрдХреНрд╖рд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдбреЗрдЯрд╛ рд╕реНрд░реЛрддреЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдЕрдореВрд░реНрдд рдХрд░ рджрд┐рдпрд╛ рддрд╛рдХрд┐ рдЙрдиреНрд╣реЗрдВ рдпрд╣ рдкрддрд╛ рди рдЪрд▓реЗ рдХрд┐ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ F
рд▓рд┐рдП рдХрдВрдЯреЗрдирд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдиреЗрдЯрд╡рд░реНрдХ DataSource
рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
class RemoteDataSource<F>(A: Async<F>) : DataSource<F>, Async<F> by A { private val internetStorage: Map<User, List<Task>> = mapOf(User(UserId("user2")) to listOf(Task("Remote Task assigned to user2"))) override fun allTasksByUser(user: User): Kind<F, List<Task>> = async { callback: (Either<Throwable, List<Task>>) -> Unit -> Option.fromNullable(internetStorage[user]).fold( { callback(UserNotInRemoteStorage(user).left()) }, { callback(it.right()) } ) } }
рд▓реЗрдХрд┐рди рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рдЕрдВрддрд░ рд╣реИ: рдПрдкреНрд▓рд┐рдХреЗрд░рд┐рдпрд▓ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдХреЗ рдмрдЬрд╛рдп, рд╣рдо рдПрдХ рдЕрдиреНрдп рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдЬреИрд╕реЗ: Async
ред
рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдиреЗрдЯрд╡рд░реНрдХ рдХреЙрд▓ рдкреНрд░рдХреГрддрд┐ рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╣реИрдВред рд╣рдо рдХреЛрдб рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд░реВрдк рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЗрд╕рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдП рдЧрдП рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рддрд░реНрдХрд╕рдВрдЧрдд рд╣реИред
рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╕рдВрдЪрд╛рд▓рди рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдХрд┐рд╕реА рднреА рдХреЙрд▓рдмреИрдХ рдСрдкрд░реЗрд╢рди рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдо рдЕрднреА рднреА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ, рд╣рдо рдмрд╕ рдкреНрд░рдХреГрддрд┐ рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдПрдХ рдСрдкрд░реЗрд╢рди рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВред
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рд░реНрдп рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
override fun allTasksByUser(user: User): Kind<F, List<Task>> = async { callback: (Either<Throwable, List<Task>>) -> Unit -> Option.fromNullable(internetStorage[user]).fold( { callback(UserNotInRemoteStorage(user).left()) }, { callback(it.right()) } ) }
рд╣рдо рдлрд╝рдВрдХреНрд╢рди рдХреЛ async {}
рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рд╣рдореЗрдВ рдСрдкрд░реЗрд╢рди рдХреЛ рдЕрдиреБрдХрд░рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЯрд╛рдЗрдк Async
рдПрдХ рд╡рд░реНрдЧ рдХреЗ рд╕рд╛рде рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдкреНрд░рдХрд╛рд░ Kind<F, List<Task>>
рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рддрд╛ рд╣реИ Kind<F, List<Task>>
рдЬрд┐рд╕реЗ asynchronously рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдпрджрд┐ рд╣рдо рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ рдХрд┐ Async.async {}
, Async.async {}
Observable.create()
, рдпрд╛рдиреА рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдЧрд╛ред рдПрдХ рдСрдкрд░реЗрд╢рди рдмрдирд╛рдирд╛, рдЬрд┐рд╕реЗ рд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдпрд╛ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХреЛрдб рд╕реЗ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреИрд╕реЗ Thread
рдпрд╛ AsyncTask
ред
callback
рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдкрд░рд┐рдгрд╛рдореА рдХреЙрд▓рдмреИрдХ рдХреЛ рдХрдВрдЯреЗрдирд░ рд╕рдВрджрд░реНрдн F
рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдПрдХ рдЙрдЪреНрдЪ рдкреНрд░рдХрд╛рд░ рд╣реИред
рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдорд╛рд░рд╛ RemoteDataSource
рд╕рд╛рд░ рд╣реИ рдФрд░ рдЕрднреА рднреА F
рдЕрдЬреНрдЮрд╛рдд рдХрдВрдЯреЗрдирд░ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ F
рдЪрд▓рд┐рдП рдПрдмреНрд╕рдЯреНрд░реИрдХреНрд╢рди рдХреЗ рд╕реНрддрд░ рддрдХ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рд╣рдорд╛рд░реА рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдкрд░ рдПрдХ рдФрд░ рдирдЬрд╝рд░ рдбрд╛рд▓рддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдкрдХреЛ рдпрд╛рдж рд╣реИ, рддреЛ рдкрд╣рд▓реЗ рд╣рдореЗрдВ LocalDataSource
рдореЗрдВ Task
рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреА рдЦреЛрдЬ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдХреЗрд╡рд▓ рддрдм (рдпрджрд┐ рд╡реЗ рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рдирд╣реАрдВ рдорд┐рд▓реЗ рдереЗ) RemoteLocalDataSource
рд╕реЗ рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред
class TaskRepository<F>( private val localDS: DataSource<F>, private val remoteDS: RemoteDataSource<F>, AE: ApplicativeError<F, Throwable>) : ApplicativeError<F, Throwable> by AE { fun allTasksByUser(user: User): Kind<F, List<Task>> = localDS.allTasksByUser(user).handleErrorWith { when (it) { is UserNotInLocalStorage -> remoteDS.allTasksByUser(user) else -> raiseError(UnknownError(it)) } } }
ApplicativeError<F, Throwable>
рдлрд┐рд░ рд╕реЗ рд╣рдорд╛рд░реЗ рд╕рд╛рде рд╣реИ! рдпрд╣ рдХрд┐рд╕реА рднреА рдЙрдЪреНрдЪ рдЕрдВрдд рд░рд┐рд╕реАрд╡рд░ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдлрд╝рдВрдХреНрд╢рди handleErrorWith()
рдлрд╝рдВрдХреНрд╢рди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред
рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
fun <A> Kind<F, A>.handleErrorWith(f: (E) -> Kind<F, A>): Kind<F, A>
рдХреНрдпреЛрдВрдХрд┐ localDS.allTasksByUser(user)
Kind<F, List<Task>>
рд░рд┐рдЯрд░реНрди рджреЗрддрд╛ рд╣реИ Kind<F, List<Task>>
, рдЬрд┐рд╕реЗ F<List<Task>>
рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ F
рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рдмрдирд╛ рд╣реБрдЖ рд╣реИ, рд╣рдо рдЗрд╕рдХреЗ рдКрдкрд░ рд╕реЗ handleErrorWith()
рдХреЛ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
handleErrorWith()
рдЖрдкрдХреЛ рдЧреБрдЬрд╝рд░реЗ рд╣реБрдП рд▓реИрдореНрдмреНрдбрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЪрд▓реЛ рд╕рдорд╛рд░реЛрд╣ рдкрд░ рдПрдХ рдХрд░реАрдм рджреЗрдЦреЛ:
fun allTasksByUser(user: User): Kind<F, List<Task>> = localDS.allTasksByUser(user).handleErrorWith { when (it) { is UserNotInLocalStorage -> remoteDS.allTasksByUser(user) else -> raiseError(UnknownError(it)) } }
рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдореЗрдВ рдкрд╣рд▓реЗ рдСрдкрд░реЗрд╢рди рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдорд┐рд▓рддрд╛ рд╣реИ, рд╕рд┐рд╡рд╛рдп рдЗрд╕рдХреЗ рдХрд┐ рдЬрдм рдПрдХ рдЕрдкрд╡рд╛рдж рдХреЛ рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЕрдкрд╡рд╛рдж рд▓рд╛рдВрдмрд╛ рджреНрд╡рд╛рд░рд╛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрджрд┐ рддреНрд░реБрдЯрд┐ UserNotInLocalStorage
рдкреНрд░рдХрд╛рд░ рдХреА рд╣реИ, рддреЛ рд╣рдо UserNotInLocalStorage
рдореЗрдВ Tasks
рдкреНрд░рдХрд╛рд░ рдХреА рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВрдЧреЗред рдЕрдиреНрдп рд╕рднреА рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рд╣рдо рдЕрдЬреНрдЮрд╛рдд рддреНрд░реБрдЯрд┐ рдХреЛ F
рдХрдВрдЯреЗрдирд░ рдореЗрдВ рд▓рдкреЗрдЯрддреЗ рд╣реИрдВ F
рдирд┐рд░реНрднрд░рддрд╛ рдореЙрдбреНрдпреВрд▓ рдкрд┐рдЫрд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рдорд╛рди рд╣реИ:
class Module<F>(A: Async<F>) { private val localDataSource: LocalDataSource<F> = LocalDataSource(A) private val remoteDataSource: RemoteDataSource<F> = RemoteDataSource(A) val repository: TaskRepository<F> = TaskRepository(localDataSource, remoteDataSource, A) }
рдЕрдВрддрд░ рдХреЗрд╡рд▓ рдЗрддрдирд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЕрдм рд╕рд╛рд░ рд╣реИ рдФрд░ F
рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдмрд╣реБрд░реВрдкреА рд░рд╣рддрд╛ рд╣реИред рдореИрдВрдиреЗ рд╢реЛрд░ рдХреЗ рд╕реНрддрд░ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛рдирдмреВрдЭрдХрд░ рдЗрд╕ рдкрд░ рдзреНрдпрд╛рди рдирд╣реАрдВ рджрд┐рдпрд╛, рд▓реЗрдХрд┐рди Async
рдПрдкреНрдЯреАрдЯреНрдпреВрдЯрд░ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рдХрд╛рд░реНрдпрдХреНрд░рдо рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд╕рднреА рд╕реНрддрд░реЛрдВ рдкрд░ рдЗрд╕рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдмрд╣реБрд░реВрдкрддрд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг
рдЕрдВрдд рдореЗрдВ, рд╣рдорд╛рд░рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрдВрдЯреЗрдирд░реЛрдВ ( F
) рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢рд┐рд╖реНрдЯ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдЙрдкрдпреЛрдЧ рд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рд╣реИ рдФрд░ рд╣рдо рд░рдирдЯрд╛рдЗрдо рдореЗрдВ рдкреЙрд▓рд┐рдлреЙрд░реНрдорд┐рдЬреНрдо рдХреЗ рдкрд░реАрдХреНрд╖рдг рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдо рдЯрд╛рдЗрдк F
рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкреНрд░рдХрд╛рд░ рдХреЗ рдбреЗрдЯрд╛ рдкрд╛рд╕ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХреЛрдб рдХреЗ рдПрдХ рд╣реА рдЯреБрдХрдбрд╝реЗ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВрдЧреЗ F
рдкрд░рд┐рджреГрд╢реНрдп рд╡реИрд╕рд╛ рд╣реА рд╣реИ рдЬрдм рд╣рдордиреЗ Observable
рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛ред
рдХрд╛рд░реНрдпрдХреНрд░рдо рдЗрд╕ рддрд░рд╣ рд╕реЗ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рд╣рдо рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд╛рд░ рдХреА рд╕реАрдорд╛рдУрдВ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛ рд▓реЗрддреЗ рд╣реИрдВ рдФрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд┐рд╡рд░рдг рдХреЛ рд╡рд╛рдВрдЫрд┐рдд рд░реВрдк рдореЗрдВ рдмрддрд╛ рд╕рдХрддреЗ рд╣реИрдВред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, RxJava рд╕реЗ рдПрдХ рдХрдВрдЯреЗрдирд░ рдХреЗ рд░реВрдк рдореЗрдВ F
Single
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред
object test { @JvmStatic fun main(args: Array<String>): Unit { val user1 = User(UserId("user1")) val user2 = User(UserId("user2")) val user3 = User(UserId("unknown user")) val singleModule = Module(SingleK.async()) singleModule.run { repository.allTasksByUser(user1).fix().single.subscribe(::println, ::println) repository.allTasksByUser(user2).fix().single.subscribe(::println, ::println) repository.allTasksByUser(user3).fix().single.subscribe(::println, ::println) } } }
рдЕрдиреБрдХреВрд▓рддрд╛ рдХреЗ рд▓рд┐рдП, рдПрд░реЛ рдкреНрд░рд╕рд┐рджреНрдз рдкреБрд╕реНрддрдХрд╛рд▓рдп рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдЖрд╡рд░рдг рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ SingleK
рд░реИрдкрд░ рд╣реИред рдпреЗ рд░реИрдкрд░ рдЖрдкрдХреЛ рдЙрдЪреНрдЪ рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрди рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВред
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдВрд╕реЛрд▓ рдкрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛:
[Task(value=LocalTask assigned to user1)] [Task(value=Remote Task assigned to user2)] UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user)))
рдпрджрд┐ Observable
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ рддреЛ рд╡рд╣реА рдкрд░рд┐рдгрд╛рдо рд╣реЛрдЧрд╛ред
рдЕрдм рдЖрдЗрдП, Maybe
рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВ, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП Maybe
MaybeK
рд░реИрдкрд░ MaybeK
:
@JvmStatic fun main(args: Array<String>): Unit { val user1 = User(UserId("user1")) val user2 = User(UserId("user2")) val user3 = User(UserId("unknown user")) val maybeModule = Module(MaybeK.async()) maybeModule.run { repository.allTasksByUser(user1).fix().maybe.subscribe(::println, ::println) repository.allTasksByUser(user2).fix().maybe.subscribe(::println, ::println) repository.allTasksByUser(user3).fix().maybe.subscribe(::println, ::println) } }
рдПрдХ рд╣реА рдкрд░рд┐рдгрд╛рдо рдХрдВрд╕реЛрд▓ рдкрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рдЕрдм рдПрдХ рдЕрд▓рдЧ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░:
[Task(value=LocalTask assigned to user1)] [Task(value=Remote Task assigned to user2)] UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user)))
рдХреНрдпрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ ObservableK
/ FlowableK
?
рдЖрдЗрдП рдЗрд╕реЗ рдЖрдЬрдорд╛рдПрдБ:
object test { @JvmStatic fun main(args: Array<String>): Unit { val user1 = User(UserId("user1")) val user2 = User(UserId("user2")) val user3 = User(UserId("unknown user")) val observableModule = Module(ObservableK.async()) observableModule.run { repository.allTasksByUser(user1).fix().observable.subscribe(::println, ::println) repository.allTasksByUser(user2).fix().observable.subscribe(::println, ::println) repository.allTasksByUser(user3).fix().observable.subscribe(::println, ::println) } val flowableModule = Module(FlowableK.async()) flowableModule.run { repository.allTasksByUser(user1).fix().flowable.subscribe(::println) repository.allTasksByUser(user2).fix().flowable.subscribe(::println) repository.allTasksByUser(user3).fix().flowable.subscribe(::println, ::println) } } }
рд╣рдо рдХрдВрд╕реЛрд▓ рдореЗрдВ рджреЗрдЦреЗрдВрдЧреЗ:
[Task(value=LocalTask assigned to user1)] [Task(value=Remote Task assigned to user2)] UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user))) [Task(value=LocalTask assigned to user1)] [Task(value=Remote Task assigned to user2)] UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user)))
рд╕рдм рдХреБрдЫ рдЙрдореНрдореАрдж рдХреЗ рдореБрддрд╛рдмрд┐рдХ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рдЖрдЗрдП kotlinx.coroutines.Deferred
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ, рдЯрд╛рдЗрдк kotlinx.coroutines.Deferred
рд▓рд┐рдП рдПрдХ рдЖрд╡рд░рдгред kotlinx.coroutines.Deferred
:
object test { @JvmStatic fun main(args: Array<String>): Unit { val user1 = User(UserId("user1")) val user2 = User(UserId("user2")) val user3 = User(UserId("unknown user")) val deferredModule = Module(DeferredK.async()) deferredModule.run { runBlocking { try { println(repository.allTasksByUser(user1).fix().deferred.await()) println(repository.allTasksByUser(user2).fix().deferred.await()) println(repository.allTasksByUser(user3).fix().deferred.await()) } catch (e: UserNotInRemoteStorage) { println(e) } } } } }
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, рдХреЙрд░рдЯреАрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдЕрдкрд╡рд╛рдж рдХреЛ рд╕рдВрднрд╛рд▓рдирд╛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред , , .
тАФ :
[Task(value=LocalTask assigned to user1)] [Task(value=Remote Task assigned to user2)] UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user)))
Arrow API DeferredK
. runBlocking
:
object test { @JvmStatic fun main(args: Array<String>): Unit { val user1 = User(UserId("user1")) val user2 = User(UserId("user2")) val user3 = User(UserId("unknown user")) val deferredModuleAlt = Module(DeferredK.async()) deferredModuleAlt.run { println(repository.allTasksByUser(user1).fix().unsafeAttemptSync()) println(repository.allTasksByUser(user2).fix().unsafeAttemptSync()) println(repository.allTasksByUser(user3).fix().unsafeAttemptSync()) } } }
[ Try
]({{ '/docs/arrow/core/try/ru' | relative_url }}) (.., Success
Failure
).
Success(value=[Task(value=LocalTask assigned to user1)]) Success(value=[Task(value=Remote Task assigned to user2)]) Failure(exception=UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user))))
, , IO
.
IO
, in/out , , .
object test { @JvmStatic fun main(args: Array<String>): Unit { val user1 = User(UserId("user1")) val user2 = User(UserId("user2")) val user3 = User(UserId("unknown user")) val ioModule = Module(IO.async()) ioModule.run { println(repository.allTasksByUser(user1).fix().attempt().unsafeRunSync()) println(repository.allTasksByUser(user2).fix().attempt().unsafeRunSync()) println(repository.allTasksByUser(user3).fix().attempt().unsafeRunSync()) } } }
Right(b=[Task(value=LocalTask assigned to user1)]) Right(b=[Task(value=Remote Task assigned to user2)]) Left(a=UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user))))
IO
тАФ . Either<L,R>
( ). , "" Either
, "" , . Right(...)
, , Left(...)
.
.
, . , , , .
.
тАж ?
, , . .
: , (, ), тАФ . , .
, . . () ( ) , .
(), , (). , .
, . , ( ).
, API . ( map
, flatMap
, fold
, ). , , Kotlin, Arrow тАФ .
DI ( ), .., DI " ". , , . DI, .., , .
, , . , .., , .
, .
, , , , .
, . тАФ Twitter: @JorgeCastilloPR .
(, ) :
FP to the max John De Goes FpToTheMax.kt
, arrow-examples
. , , .