Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Coroutines: Como solución para tu aplicación

Coroutines: Como solución para tu aplicación

Dinorah Tovar

August 10, 2019
Tweet

More Decks by Dinorah Tovar

Other Decks in Technology

Transcript

  1. Coroutines Son componentes para crear subtareas multirutina, que pueden ser

    suspendidas y reanudadas. 
 Una manera más fácil de decir que en Kotlin tenemos formas de hace Suspendable computation Disponible para todas los lugares donde Kotlin esta soportado. Mobile, Cloud, Multi-platform o Web
  2. Asynchronous programming userRemoteDataSource.getUser() .subscribe(object : ResourceObserver<User>() { override fun onComplete()

    { } override fun onNext(value: User) { titleUserName?.text = user?.name } override fun onError(e: Throwable) { } }) Out of memory exception
  3. Asynchronous programming userRemoteDataSource.getUser() .subscribe(object : ResourceObserver<User>() { override fun onComplete()

    { disposable() } override fun onNext(value: User) { titleUserName?.text = user?.name } override fun onError(e: Throwable) { disposable() } })
  4. Asynchronous programming fun getUser(): Observable<User> { //Return observable } fun

    getToken(): Observable<Token> { //Return observable } fun subscribeNotification(): Observable<Boolean> { //Return observable }
  5. Asynchronous programming fun getUser(): Observable<User> {…} fun getToken(): Observable<Token> {…}

    fun subscribeNotification(): Observable<Boolean> {…} fun loginUser() { getUser() getToken() subscribeNotification() }
  6. Asynchronous programming private fun getToken(): Single<Token>> { ... } private

    fun subscribeNotifications(): Single<Boolean> { return userRemoteDataSource.subscribeNotifications() .flatMap { boolean -> userRemoteDataSource.subscribeOther .subscribeOn(...) }
  7. Asynchronous programming fun loginUser() { val rxToken = getToken() val

    rxNotifications = subscribeNotifications() Single.zip(rxToken, rxNotifications, BiFunction<Token, Boolean, Token> { getUser() }) }
  8. RxJava Es una librería muy poderosa, todo mundo la ha

    usado, pero no es una librería para manejar async work. Es una librería de procesamiento de eventos.
  9. Coroutines Muchos creen que aunque podría solucionar el problema, le

    falta madurez, y algunos desarrolladores creen que representa una curva de aprendizaje. Robusto Simple Readable
  10. Coroutines suspend fun initCoroutine() { val jobs = List(100_000) {

    GlobalScope.launch { delay(1000) Log.d (" . ") } } jobs.forEach{ it.join() } } Coroutines son parecidos a thread
  11. Coroutines suspend fun initCoroutine() { val jobs = List(100_000) {

    GlobalScope.launch { delay(1000) Log.d (" . ") } } jobs.forEach{ it.join() } } Coroutines son parecidos a light-weight thread
  12. Coroutines suspend fun initCoroutine() { val jobs = List(100_000) {

    GlobalScope.launch { delay(1000) Log.d (" . ") } } jobs.forEach{ it.join() } } Coroutines son parecidos a light-weight thread
  13. Coroutines suspend fun initCoroutine() { val jobs = List(100_000) {

    GlobalScope.launch { delay(1000) Log.d (" . ") } } jobs.forEach{ it.join() } } Coroutines son parecidos a light-weight thread
  14. Coroutines Coroutines son parecidos a light-weight thread Coroutines son State

    Machine objects Data for each state Y puedes pausarlos y reanudarlos
  15. Coroutines userRemoteDataSource.getUser() .subscribe(object : ResourceObserver<User>() { override fun onComplete() {

    } override fun onNext(value: User) { titleUserName?.text = user?.name } override fun onError(e: Throwable) { } })
  16. Coroutines Dispatchers Multiple flavors Dispatchers.Main Main thread, UI, solo trabajo

    ligero Dispatchers.IO Lejos del Main Thread, trabajo de network or disk Dispatchers.Default Lejos de Main Thread, trabajo en el CPU
  17. Coroutines network request We get our result asynchronous and can

    be: We show the result to the main thread We make a call We create a coroutine scope await() Success<T> withContext{ } launch{ }
  18. Network Request fun getUserName() { GlobalScope.launch { var user =

    userRemoteDataSource.getUser() showUserName(user?.name) } }
  19. Network Request fun getUserName() { GlobalScope.launch { var user =

    userRemoteDataSource.getUser() showUserName(user?.name) } }
  20. Network Request fun getUserName() { GlobalScope.launch { var user =

    userRemoteDataSource.getUser() withContext(Dispatchers.Main) { showUserName(user?.name) } } }
  21. Room @Insert suspend fun insertUser(user: UserEntity) @Override public Object insertUserSuspend(final

    UserEntity user,final Continuation<?super Unit> p1){ return CoroutinesRoom.execute(__db, new Callable<Unit>() { @Override public Unit call() throws Exception { __db.beginTransaction(); try { __insertionAdapterOfUser.insert(user); __db.setTransactionSuccessful(); return kotlin.Unit.INSTANCE; } finally { __db.endTransaction(); } } }, p1); } Room 2.2.0
  22. Workers class MyWorker (ctx: Context, params: WorkerParameters): Worker(ctx, params) {

    override fun doWork(): Result { return try { userRemoteDataSource.syncBookmarks() userLocalDataSource.updateUser() Result.success() } catch (ex: Exception) { Result.failure() } } }
  23. Workers override fun doWork(): Result { userRemoteDataSource.syncBookmarks() if(isStoped()) return Result.failure()

    userLocalDataSource.updateUser() if(isStoped()) return Result.failure() return Result.success() }
  24. Workers class MyWorker (ctx: Context, params: WorkerParameters) : CoroutineWorker(context, params)

    { override fun doWork(): Result = withContext(Dispatchers.IO) { userRemoteDataSource.syncBookmarks() userLocalDataSource.updateUser() return Result.success() } } Work-Runtime 2.0.0
  25. LiveData val user: LiveData<User> = liveData { val data =

    userRemoteDataSource.getUser() emit(data) }
  26. LiveData val user: LiveData<Result> = liveData { emit(Result.loading()) try {

    emit(Result.success(fetchUser()) } catch(ioException: Exception) { emit(Result.error(ioException)) } }
  27. ViewModel ViewModel se encarga de almacenar y manejar la información

    relacionada con el UI tomando en cuenta el ciclo de vida de la aplicación
  28. Coroutines Leak class MainViewModel : ViewModel() { private val viewModelJob

    = SupervisorJob() val scope = CoroutineScope(Dispatchers.IO + viewModelJob) fun getUser() = scope.launch { //Do some suspendable and ultra hardcore code } }
  29. Coroutines Leak class MainViewModel : ViewModel() { private val viewModelJob

    = SupervisorJob() val scope = CoroutineScope(Dispatchers.IO + viewModelJob) fun getUser() = scope.launch { //Do some suspendable and ultra hardcore code } override fun onCleared() { super.onCleared() viewModelJob.cancel() } }
  30. Unit testing and Coroutines @Before fun before() { MockitoAnnotations.initMocks(this) Dispatchers.setMain(Dispatchers.Unconfined)

    } @Test fun createFirstTimeTrue() { runBlocking { val user = userLocalDataSource.getUser() verify(user).`is`.yourUser } }
  31. Unit testing and Room @Test fun insertAndGetUser() = runBlocking {

    userDao.insertUser(user) val userAvailable = userDao.getUser() assertEquals(user, userAvailable) }
  32. Unit testing and Room @RunWith(JUnit4::class) class MyWorkTest { @Test fun

    testMyWork() { val worker = TestListenableWorkerBuilder<MyWorker>(mockContext).build() val result = worker.startWork().get() assertThat(result, `is`(Result.success())) } }