[1B4]안드로이드 동시성_프로그래밍

247
안드로이드 동시성 프로그래밍 - RxJava를 활용한 Functional Reactive Programming 최정열 / Sivaworks / 라 스칼라 코딩단 email: [email protected] 조현태 / Line + / 라 스칼라 코딩단 email: [email protected]

description

DEVIEW 2014 [1B4]안드로이드 동시성_프로그래밍

Transcript of [1B4]안드로이드 동시성_프로그래밍

Page 1: [1B4]안드로이드 동시성_프로그래밍

안드로이드 동시성 프로그래밍 - RxJava를 활용한 Functional Reactive Programming

최정열 / Sivaworks / 라 스칼라 코딩단email: [email protected]

조현태 / Line + / 라 스칼라 코딩단email: [email protected]

Page 2: [1B4]안드로이드 동시성_프로그래밍

오늘의 목표

Page 3: [1B4]안드로이드 동시성_프로그래밍

오늘의 목표

함수형 프로그래밍에 한 번 관심을 가져보시는 것은 어떨까요?!함수형을 프로그래밍을 익히는 것이 가장 큰 도전…!더 어려운 부분은 절차형과 함수형에서 효율적인 방법을 선택하는 것!!라 스칼라 코딩단: https://groups.google.com/forum/#!forum/scala-korea!샘플 저장소: https://github.com/orgs/FridayCoders/dashboard (업데이트 예정)!

Page 4: [1B4]안드로이드 동시성_프로그래밍

1. Plain Old Java Concurrent Programming2. 생명주기와 동시성 프로그래밍3. Sequencial Tasks & Parellel Tasks4. 람다 & 함수형 프로그래밍

안드로이드 동시성 프로그래밍

Page 5: [1B4]안드로이드 동시성_프로그래밍

동시성 관련클래스 & 패키지

Page 6: [1B4]안드로이드 동시성_프로그래밍

Android Concurrent Programming

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

otto

Page 7: [1B4]안드로이드 동시성_프로그래밍

Thread

Concurrent Programming

new Thread() { @Override public void run() { URL url = new URL(strUrl); HttpURLConnection urlConnection = ... urlConnection.connect(); iStream = urlConnection.getInputStream(); bitmap = BitmapFactory.decodeStream(iStream); } }.start();

Background

Page 8: [1B4]안드로이드 동시성_프로그래밍

메인 쓰레드의 메시지큐로 전달

Thread class

new Thread() { @Override public void run() { URL url = new URL(strUrl); HttpURLConnection urlConnection = ... urlConnection.connect(); iStream = urlConnection.getInputStream(); bitmap = BitmapFactory.decodeStream(iStream); ! runOnUiThread(new Runnable() { @Override public void run() { imageView.setImageBitmap(bitmap); } } }.start();

UI Thread

Page 9: [1B4]안드로이드 동시성_프로그래밍

예외 발생!

Thread class

new Thread() { @Override public void run() { try{ URL url = new URL(strUrl); HttpURLConnection urlConnection = ... urlConnection.connect(); iStream = urlConnection.getInputStream(); bitmap = BitmapFactory.decodeStream(iStream); } catch (Exception e){ log(e.toString); } runOnUiThread(new Runnable() { @Override public void run() { imageView.setImageBitmap(bitmap); } } }.start();

Background

Page 10: [1B4]안드로이드 동시성_프로그래밍

예외는 백그라운드에서 발생하지만, 메시지는 UI쓰레드로…

Thread class

new Thread() { @Override public void run() { try{ URL url = new URL(strUrl); HttpURLConnection urlConnection = ... urlConnection.connect(); iStream = urlConnection.getInputStream(); bitmap = BitmapFactory.decodeStream(iStream); } catch (Exception e){ log(e.toString); runOnUiThread(new Runnable(){ showToast(“다운로드가 실패했습니다.”); }); } runOnUiThread(new Runnable() { @Override public void run() { imageView.setImageBitmap(bitmap); } } }.start();

Background

UI Thread

Page 11: [1B4]안드로이드 동시성_프로그래밍

예외 처리 …

Thread class

... try{ URL url = new URL(strUrl); HttpURLConnection urlConnection = ... urlConnection.connect(); iStream = urlConnection.getInputStream(); bitmap = BitmapFactory.decodeStream(iStream); } catch (MalformedURLException e){ log.e(e.toString); } catch (IOException e){ runOnUiThread(new Runnable(){ showToast(“다운로드가 실패했습니다.”); }); } catch (Exception e){ // ... } ...

Page 12: [1B4]안드로이드 동시성_프로그래밍

리팩토링

Thread class

Bitmap downloadUrl(String strUrl) { try { iStream = getInputStream(strUrl); } catch (Exception e) { handleException(e, new OnError(){ String onError(){ return “다운로드 실패”; } }); } finally { close(iStream); } return BitmapFactory.decodeStream(iStream); } !private void handleException(Exception e, OnError onError) { ... }

보기 편하게 람다식으로…

Page 13: [1B4]안드로이드 동시성_프로그래밍

구현을 보지 않으면 어떤 쓰레들에서 동작하는지 모르겠다…

Thread class

Bitmap downloadUrl(String strUrl) { try { iStream = getInputStream(strUrl); } catch (Exception e) { handleException(e, ()-> { “다운로드 실패” }); } finally { close(iStream); } return BitmapFactory.decodeStream(iStream); } !private void handleException(Exception e, OnError onError) { ... }

이 메소드는 백그라운드? 아님, UI Trehad? !

구현을 들여다 보지 않으면 모르겠는걸?

Page 14: [1B4]안드로이드 동시성_프로그래밍

현재 쓰레드에서 메소드 호출과 UI쓰레드 호출을 비교

Thread class

Bitmap downloadUrl(String strUrl) { ... handleException(e, ()-> “다운로드 실패” ); } !!!// 1 void handleException(Exception e, OnError onError) { runOnUiThread(new Runnable(){ void run(){ log.d(onError.call());} } } !// 2 void handleException(Exception e, OnError onError) { log.d(onError.call()); } 현재 쓰레드 (Background)

UI 쓰레드

로깅은 백그라운드에서 처리해도 되는데, UI 쓰레드에서 호출하는건 낭비 닐까?

Page 15: [1B4]안드로이드 동시성_프로그래밍

오류를 뷰에 반영하고 싶은데…

Thread class

Bitmap downloadUrl(String strUrl) { ... handleException(e, ()-> { Toast.makeText(getActivity(), ()-> { textView.setText(“다운로드 실패”) }}); } !// 1 void handleException(Exception e, OnError onError) { runOnUiThread(new Runnable(){ void run(){ onError.call(); } } } !// 2 void handleException(Exception e, OnError onError) { onError.call(); }

뷰를 조작하는 코드를 전달 하면?

Page 16: [1B4]안드로이드 동시성_프로그래밍

CalledFromWrongThreadException

Thread class

Bitmap downloadUrl(String strUrl) { ... handleException(e, ()-> { Toast.makeText(getActivity(), ()-> { textView.setText(“다운로드 실패”) }}); } !// 1 void handleException(Exception e, OnError onError) { runOnUiThread(new Runnable(){ void run(){ onError.call(); } } } !// 2 -> CalledFromWrongThreadException void handleException(Exception e, OnError onError) { onError.call(); }

UI 쓰레드 외에서는 뷰를 조작 할 수 없음!

Page 17: [1B4]안드로이드 동시성_프로그래밍

모든 메소드에 어떤 쓰레드에서 작동하는지 이름을 붙여보자.

Thread class

Bitmap downloadUrl(String strUrl) { ... handleException(e, ()-> { Toast.makeText(getActivity(), ()-> { textView.setText(“다운로드 실패”) }}); } !// 1 void handleExceptionOnBgThread(Exception e, OnError onError) { runOnUiThread(new Runnable(){ void run(){ onError.call(); } } } !// 2 void handleExceptionOnUiThread(Exception e, OnError onError) { onError.call(); }

모든 메소드의 이름을 이렇게 짓는 것은 무리야!

Page 18: [1B4]안드로이드 동시성_프로그래밍

생명주기와 쓰레드

Life Cycle

Page 19: [1B4]안드로이드 동시성_프로그래밍

쓰레드를 시작했으면 독립적으로 존재

생명주기와 쓰레드

ThreadBackground

UI Thread Activity A

onDestroy()

Activity B

Activity A가 종료 되어도 쓰레드는 독립적으로 살아 있음

Page 20: [1B4]안드로이드 동시성_프로그래밍

Inner class 사용시 메무리 누수

생명주기와 쓰레드

ThreadBackground

UI ThreadActivity A

Reference

Activity B

onDestroy()

Inner class로 쓰레드를 만들면 암북적으로 액티비티를 참조

쓰레드가 암묵적으로 참조하고 있어서, onDestroy()가 호출 된

후에도, GC되지 않음!

성능 저하, 메모리 낭비

Page 21: [1B4]안드로이드 동시성_프로그래밍

쓰레드를 종료 시킬 깔끔한 방법의 필요성

생명주기와 쓰레드

ThreadBackground

UI Thread Activity A

어디선간 쓰레드를 종료 해야겠네!

onStop() onDestroy()

어떻게 종료 시키지? interrupt?

또, try ~ catch ~ final?

Page 22: [1B4]안드로이드 동시성_프로그래밍

Callback 을 사용한 Thread class

생명주기와 쓰레드

MyThread extends Thread{ interface MyCallback { void onFinishDownloadImage(T t); } ! MyCallback callback; ! @Override public void run() { // download image... runOnUiThread(new Runnable() { @Override public void run() { callback.onFinishDownloadImage(bitmap); } } };

모든 blocking 작업이 끝나면 콜백을 통해 결과를 전달~

Page 23: [1B4]안드로이드 동시성_프로그래밍

예외 발생

생명주기와 쓰레드

MyThread extends Thread{ interface MyCallback { void onFinishDownloadImage(T t); void onError(Exception e); } ! MyCallback callback; ! @Override public void run() { try { // download image… } catch { callback.onError(e); } runOnUiThread(new Runnable() { @Override public void run() { callback.onFinishDownloadImage(bitmap); } } };

예외 발생시 유저에게 알려야 하는데, UI요소에는 직접 처리 할 수 없으므로

콜백 메소드를 추가.

Page 24: [1B4]안드로이드 동시성_프로그래밍

Android Concurrent Programming

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

otto

Executor + Thread pool + Future …

Thread 보다 추상화된 제어가 가능!

Page 25: [1B4]안드로이드 동시성_프로그래밍

Android Concurrent Programming

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

otto

안드로이드의 UI Thread를 관리하는 놈.

Looper와 함께 사용하고, Looper는 메시지

큐를 가지고 있어서 순차 실행을 보장!

Page 26: [1B4]안드로이드 동시성_프로그래밍

Android Concurrent Programming

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

otto

Handler + 탬플릿 메소드 패턴

Page 27: [1B4]안드로이드 동시성_프로그래밍

다운로드 + Ui + 예외 처리 (?)

AsyncTask class

@Override protected void onPreExecute() { progressBar.setVisibility(View.VISIBLE); } !@Override protected Bitmap doInBackground(String... params) { try { bitmap = downloadBitmap(params); } catch (Exception e) {...} return bitmap; } !@Override protected void onPostExecute(Bitmap bitmap) { imageView.setImageBitmap(bitmap); progressBar.setVisibility(View.GONE); }

UI 쓰레드

Page 28: [1B4]안드로이드 동시성_프로그래밍

다운로드 + Ui + 예외 처리 (?)

AsyncTask class

@Override protected void onPreExecute() { progressBar.setVisibility(View.VISIBLE); } !@Override protected Bitmap doInBackground(String... params) { try { bitmap = downloadBitmap(params); } catch (Exception e) {...} return bitmap; } !@Override protected void onPostExecute(Bitmap bitmap) { imageView.setImageBitmap(bitmap); progressBar.setVisibility(View.GONE); }

백그라운드 쓰레드

Page 29: [1B4]안드로이드 동시성_프로그래밍

다운로드 + Ui + 예외 처리 (?)

AsyncTask class

@Override protected void onPreExecute() { progressBar.setVisibility(View.VISIBLE); } !@Override protected Bitmap doInBackground(String... params) { try { bitmap = downloadBitmap(params); } catch (Exception e) {...} return bitmap; } !@Override protected void onPostExecute(Bitmap bitmap) { imageView.setImageBitmap(bitmap); progressBar.setVisibility(View.GONE); }

예외는 백그라운드 쓰레드에서

발생하는데, UI Thread로 어떻

게 전달하지?

Page 30: [1B4]안드로이드 동시성_프로그래밍

Android Concurrent Programming

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

otto

액티비티의 생명 주기로 부터

영향을 받지 않음!

Page 31: [1B4]안드로이드 동시성_프로그래밍

Android Concurrent Programming

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

otto

커서관리 방법 없고,

AsyncTask와 문제점 공유

Page 32: [1B4]안드로이드 동시성_프로그래밍

Android Concurrent Programming

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

otto

허니컴 이후 등장. compat을 이용해서 이전에도

사용이 가능하며 생명주기 변경시 스스로 처리함

단, ContentProvider 외에는 사용이 어려움

Page 33: [1B4]안드로이드 동시성_프로그래밍

동시성 관련라이브러리

Page 34: [1B4]안드로이드 동시성_프로그래밍

Third Party Libraries

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

otto

네트워크, 이미지

Callback 기반

Page 35: [1B4]안드로이드 동시성_프로그래밍

Third Party Libraries

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

otto

동기, 비동기 (async) 지원

RxJava의 Observable 지원

Page 36: [1B4]안드로이드 동시성_프로그래밍

Third Party Libraries

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

otto

Page 37: [1B4]안드로이드 동시성_프로그래밍

Third Party Libraries

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

otto

Future

Page 38: [1B4]안드로이드 동시성_프로그래밍

Third Party Libraries

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

otto

@Background 어노테이션

내부적으로 ScheduledThreadPool을 활용

Page 39: [1B4]안드로이드 동시성_프로그래밍

Third Party Libraries

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

ottoListenableFuture

Page 40: [1B4]안드로이드 동시성_프로그래밍

Third Party Libraries

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

otto

이벤트 버스

RxJava로 대체 할 수 있음

Page 41: [1B4]안드로이드 동시성_프로그래밍

Third Party Libraries

Concurrent Programming

Thread

concurrent package

Handler

AsyncTask

Service

AsyncQueryHandler

Loader

Volley

OkHttp, Retrofit, Picasso

AndroidUniversalImageLoader

AndroidAsync(Http), ION

AndroidAnnotations

Guava

greenrobot/EventBus

otto

애플리케이션의 설계가 라이브러리 인터페이스에 의존적이 되는 것을 주의!

저마다 Http client, 이미지 캐싱, ThreadPool 관리 서로 다른 정책과 인터페이

스를 가지고 있으므로, 중복 설정 및 불필요한 추상화를 주의!

Page 42: [1B4]안드로이드 동시성_프로그래밍

Android Event Sources

Concurrent Programming

KEY & TOUCH

ACCELEROMETER

GRAVITY

GYROSCOPE

LIGHT

MAGNETIC

ORIENTATION

LOCATION

PRESSURE

Page 43: [1B4]안드로이드 동시성_프로그래밍

Parallel tasksConcurrently executing tasks

멀티 태스크

Sequencial tasksOne after another

Task A

Request

Task B

Task C

Task A Task B Task C

Request

Result Result

반드시 순서대로 실행 되어

야 하는 태스크 묶음

Page 44: [1B4]안드로이드 동시성_프로그래밍

흔한 로그인 시나리오

1. Auth

2. Token

3. Login

4. Result

5. Request

6. Image

Login with

순서대로 실행 되어야 함

Page 45: [1B4]안드로이드 동시성_프로그래밍

순서를 갖는 작업들

Sequencial tasks

TASK A TASK B TASK CBackground

UI Thread Req Resp

Page 46: [1B4]안드로이드 동시성_프로그래밍

Callback 만을 지원하는 라이브러리 사용시

Sequencial tasks

TASK A TASK B TASK CBackground

UI Thread Req Resp

불필요한 UI 쓰레드 점유특히, Volley

Page 47: [1B4]안드로이드 동시성_프로그래밍

구현 방식

Sequencial tasks

• Nested Callbacks

• Future combination

• SingleThreadExecutor

• Handler + Looper

Callback hell을 해결 할 수 있지만,

소스 네비게이션시 라인 점프는 늘어 날 수 있음.

하나의 쓰레드와 Task를 결합. 단, 오류 처리는 쉽지 않음

직접 워커를 만듦 커스텀 콜백 인터페이스를 정의 해야 함

Page 48: [1B4]안드로이드 동시성_프로그래밍

Callback hell

흔한 로그인 시나리오

requestFacebookLogin(new Callback() { public void onSuccess(Result result) { ... } });

Page 49: [1B4]안드로이드 동시성_프로그래밍

Callback hell

흔한 로그인 시나리오

requestFacebookLogin(new Callback() { public void onSuccess(Result result) { String facebookId = result.getFacebookId(); requestLogin(facebookId, new Callback() { ... }); } });

Page 50: [1B4]안드로이드 동시성_프로그래밍

Callback hell

흔한 로그인 시나리오

requestFacebookLogin(new Callback() { public void onSuccess(Result result) { String facebookId = result.getFacebookId(); requestLogin(facebookId, new Callback() { public void onSuccess(Result result) { result.getUserDetails(new Callback() { @Override public void onSuccess(User user) { ... } }); } }); } });

예외 처리 추가시 분기문 추가시 depth가 2배씩 증가;;

Page 51: [1B4]안드로이드 동시성_프로그래밍

재시도 전략

흔한 로그인 시나리오

requestFacebookLogin(new Callback() { public void onSuccess(Result result) { String facebookId = result.getFacebookId(); requestLogin(facebookId, new Callback() { public void onSuccess(Result result) { result.getUserDetails(new Callback() { @Override public void onSuccess(User user) { ... } }); } public void onFail(Result result){ retry( ??? ); } }); } });

각각 Task에 예외가 발생한 작업을 재시도 하고 싶을 땐?

@#!%

Page 52: [1B4]안드로이드 동시성_프로그래밍

페이스북 로그인 > 앱 서버 로그인 > 초기 데이터 요청 > 오류 처리

흔한 로그인 시나리오

requestFacebookLogin(new Callback() { public void onSuccess(Result result) { String facebookId = result.getFacebookId(); requestLogin(facebookId, new Callback() { public void onSuccess(Result result) { result.getUserDetails(new Callback() { @Override public void onSuccess(User user) { ... } }); } public void onFail(Result result){ retry( ??? ); showToast(context, R.String.loginFail); } }); } });

UI Thread를 통해 유저에게 알리고 싶은데,

“나는 누구 여긴 어디?”

Page 53: [1B4]안드로이드 동시성_프로그래밍

Parallel tasksConcurrently executing tasks

멀티 태스크

Sequencial tasksOne after another

Task A

Request

Task B

Task C

Task A Task B Task C

Request

Result Result

태스크간의 의존성이 없어, 동시

에 실행 될 수 있음.

그러나, 우리는 UI 프로그래머

Page 54: [1B4]안드로이드 동시성_프로그래밍

흔한 컨텐츠 공유 시나리오

Page 55: [1B4]안드로이드 동시성_프로그래밍

1. Req

1. Req

1. Req

1. Req

흔한 컨텐츠 공유 시나리오

Page 56: [1B4]안드로이드 동시성_프로그래밍

1. Req

2. Resp

1. Req

2. Resp

1. Req

2. Resp

1. Req

2. Resp

흔한 컨텐츠 공유 시나리오

Page 57: [1B4]안드로이드 동시성_프로그래밍

동시에 수행 해야 하는 작업들

Parellel Tasks

DataThread A

UI Thread Login Data

latency

Thread B

Thread C

Data latency

Data latency

작업이 끝나는 시간은 모두 다를 수 있음.

모든 작업이 끝났을 때, UI에 반영하고 싶은데…

Page 58: [1B4]안드로이드 동시성_프로그래밍

1. Req

2. Resp

1. Req

2. Resp

1. Req

2. Resp

1. Req

2. Resp

작업이 완료

되었습니다.

흔한 컨텐츠 공유 시나리오

Page 59: [1B4]안드로이드 동시성_프로그래밍

구현 방식

Parellel Tasks

• Creating Multiple Threads

• CountDownLatch, MultiThreadExecutor (Thread Pool)

각각의 태스크를 수행하고 flag를 통해 결과를 취합

요청이 많은 경우 쓰레드 풀을 이용

concurrent 패키지의 CountDownLatch

Page 60: [1B4]안드로이드 동시성_프로그래밍

순차 + 병렬

Composed Tasks

Task A

Request

Task B

Task C

Task A Task B Task B

Result

앱을 통해 사진과 글을 포스팅

(순차 태스크)포스팅한 글을 SNS에 공유

(병렬 태스크)

Page 61: [1B4]안드로이드 동시성_프로그래밍

어떤 데이터가 있는데…

어떤 쓰레드에서 수행하고,

필요한 데이터만 걸러내고,

데이터를 어떻게 변환하고,

오류 발생시에는 어떻게 대응할지,

어떤 쓰레드에서 결과를 받을지,

시작하면,

!

필요한 경우 취소 할 수 있어야 한다.

!

테스트도 쉬워야겠고!

유추 가능한 것은 생략 할 수 있으면 좋겠다.

이런거 없나?

Page 62: [1B4]안드로이드 동시성_프로그래밍

observable

어떤 쓰레드에서 수행하고,

필요한 데이터만 걸러내고,

데이터를 어떻게 변환하고,

오류 발생시에는 어떻게 대응할지,

어떤 쓰레드에서 결과를 받을지,

시작하면,

!

필요한 경우 취소 할 수 있어야 한다.

!

테스트도 쉬워야겠고!

유추 가능한 것은 생략 할 수 있으면 좋겠다.

이런거 없나?

Page 63: [1B4]안드로이드 동시성_프로그래밍

observable

.subscribeOn(background)

필요한 데이터만 걸러내고,

데이터를 어떻게 변환하고,

오류 발생시에는 어떻게 대응할지,

어떤 쓰레드에서 결과를 받을지,

시작하면,

!

필요한 경우 취소 할 수 있어야 한다.

!

테스트도 쉬워야겠고!

유추 가능한 것은 생략 할 수 있으면 좋겠다.

이런거 없나?

Page 64: [1B4]안드로이드 동시성_프로그래밍

observable

.subscribeOn(background)

.filter(paidUser())

데이터를 어떻게 변환하고,

오류 발생시에는 어떻게 대응할지,

어떤 쓰레드에서 결과를 받을지,

시작하면,

!

필요한 경우 취소 할 수 있어야 한다.

!

테스트도 쉬워야겠고!

유추 가능한 것은 생략 할 수 있으면 좋겠다.

이런거 없나?

Page 65: [1B4]안드로이드 동시성_프로그래밍

observable

.subscribeOn(background)

.filter(paidUser())

.map(stringToJson())

오류 발생시에는 어떻게 대응할지,

어떤 쓰레드에서 결과를 받을지,

시작하면,

!

필요한 경우 취소 할 수 있어야 한다.

!

테스트도 쉬워야겠고!

유추 가능한 것은 생략 할 수 있으면 좋겠다.

이런거 없나?

Page 66: [1B4]안드로이드 동시성_프로그래밍

observable

.subscribeOn(background)

.filter(paidUser())

.map(stringToJson())

.doOnError(handleError())

어떤 쓰레드에서 결과를 받을지,

시작하면,

!

필요한 경우 취소 할 수 있어야 한다.

!

테스트도 쉬워야겠고!

유추 가능한 것은 생략 할 수 있으면 좋겠다.

이런거 없나?

Page 67: [1B4]안드로이드 동시성_프로그래밍

observable

.subscribeOn(background)

.filter(paidUser())

.map(stringToJson())

.doOnError(handleError())

.observeOn(mainThread)

시작하면,

!

필요한 경우 취소 할 수 있어야 한다.

!

테스트도 쉬워야겠고!

유추 가능한 것은 생략 할 수 있으면 좋겠다.

이런거 없나?

Page 68: [1B4]안드로이드 동시성_프로그래밍

observable

.subscribeOn(background)

.filter(paidUser())

.map(stringToJson())

.doOnError(handleError())

.observeOn(mainThread)

.subscribe() -> subscription

!

필요한 경우 취소 할 수 있어야 한다.

!

테스트도 쉬워야겠고!

유추 가능한 것은 생략 할 수 있으면 좋겠다.

이런거 없나?

Page 69: [1B4]안드로이드 동시성_프로그래밍

observable

.subscribeOn(background)

.filter(paidUser())

.map(stringToJson())

.doOnError(handleError())

.observeOn(mainThread)

.subscribe() -> subscription

!

subscription.unsubscribe()

!

테스트도 쉬워야겠고!

유추 가능한 것은 생략 할 수 있으면 좋겠다.

이런거 없나?

Page 70: [1B4]안드로이드 동시성_프로그래밍

observable

.subscribeOn(background)

.filter(paidUser())

.map(stringToJson())

.doOnError(handleError())

.observeOn(mainThread)

.subscribe() -> subscription

!

subscription.unsubscribe()

!

!

유추 가능한 것은 생략 할 수 있으면 좋겠다.

이런거 없나?

!

assert…(paidUser())

assert…(stringToJson())

assert…(handleError())

Page 71: [1B4]안드로이드 동시성_프로그래밍

observable

.subscribeOn(background)

.filter(paidUser())

.map(stringToJson())

.doOnError(handleError())

.observeOn(mainThread)

.subscribe() -> subscription

!

subscription.unsubscribe()

!

!

이런거 없나?

Page 72: [1B4]안드로이드 동시성_프로그래밍

RxJava

Page 73: [1B4]안드로이드 동시성_프로그래밍

RxJava

로직에만 집중

테스트 용이성

가독성

이름짓기?

내가 작성하는 코드가 어떤 쓰레드에서 돌아갈지

지금 당장은 관심이 없어.

왜냐하면, 실제 사용 할 시점에서 지정하면 되니까.

모듈화가 쉽다 == 테스트하기 쉽다

메소드 체이닝, 왼쪽에서 오른쪽으로 읽자

코드가 하는 일은 코드 자체가 표현하도록 하자.

Page 74: [1B4]안드로이드 동시성_프로그래밍

3초 동안 입력이 없으면 추천 검색어를 제시

Custom Events

Page 75: [1B4]안드로이드 동시성_프로그래밍

Custom Events

D

3초 동안 입력이 없으면 추천 검색어를 제시

Page 76: [1B4]안드로이드 동시성_프로그래밍

Custom Events

D E V

3초 동안 입력이 없으면 추천 검색어를 제시

Page 77: [1B4]안드로이드 동시성_프로그래밍

Custom Events

D E V

1s

3초 동안 입력이 없으면 추천 검색어를 제시

Page 78: [1B4]안드로이드 동시성_프로그래밍

Custom Events

D E V

1s 2s

3초 동안 입력이 없으면 추천 검색어를 제시

Page 79: [1B4]안드로이드 동시성_프로그래밍

Custom Events

D E V

dev 검색 요청

1s 2s 3s

3초 동안 입력이 없으면 추천 검색어를 제시

Page 80: [1B4]안드로이드 동시성_프로그래밍

Custom Events

D E V

dev 검색 요청

1s 2s 3s

3초 동안 입력이 없으면 추천 검색어를 제시

Page 81: [1B4]안드로이드 동시성_프로그래밍

Custom Events

Custom Events

D E V

1s 2s 3s

Thread

lastInputTime 0 0 0 3

Callback

1. 쓰레드 만들고

2. 이벤트 발생 시간 기록

3. 마지막 이벤트와 현재 시간 비교

4. 설정 값 이상의 차이가 발생시 콜백

또는,

1. 수행할 태스크를 작성

2. 태스크 등록(postDelayed 사용)

3. 이벤트 발생시 등록 이벤트 취소

4. 등록 된 태스크가 수행되며 콜백

Page 82: [1B4]안드로이드 동시성_프로그래밍

람다

안드로이드 스튜디오 사용시 코드 폴딩을 통해 간결하게 표현되는 놈?

Page 83: [1B4]안드로이드 동시성_프로그래밍

람다

Runnable task = new Runnable(){ @Override public void run(){ System.out.println("Hello Lamba"); } };

Runnable task2 = () -> { System.out.println("Hello Lamba"); };

Page 84: [1B4]안드로이드 동시성_프로그래밍

람다

Runnable task = new Runnable(){ @Override public void run(){ System.out.println("Hello Lamba"); } };

Runnable task2 = () -> { System.out.println("Hello Lamba"); };

인터페이스가 하나의 메소드를 호출하면

굳이 메소드의 이름을 적을 필요는 없으니 생략

Page 85: [1B4]안드로이드 동시성_프로그래밍

람다

Runnable task = new Runnable(){ @Override public void run(){ System.out.println("Hello Lamba"); } };

Runnable task2 = () -> { System.out.println("Hello Lamba"); };

파라미터는 비었으니 빈 괄호를 넣어주자

Page 86: [1B4]안드로이드 동시성_프로그래밍

람다

Runnable task = new Runnable(){ @Override public void run(){ System.out.println("Hello Lamba"); } };

Runnable task2 = () -> { System.out.println("Hello Lamba"); };

화살표 나오면 람다식!

블럭 내의 내용은 그대로~

Page 87: [1B4]안드로이드 동시성_프로그래밍

이클립스에서 람다 사용

Xtend -> 자바 클래스로 변환

Xtend

• 안드로이드의 Swift

• 람다식은 익명 클래스를 통해 구현함

• 자바코드로 컴파일 되므로 호환성 문제가 없음

• 함수형 프로그래밍의 특징을 상당부분 수용함

• Eclipse IDE 지원

호환성 끝판왕

단점:

Eclipse에서 만들었음에도 리팩토링 기능이 취약함.

IntelliJ에서는 그냥 텍스트파일

프로젝트가 커질수록 컴파일 타임이 급격히 증가

빌드 프로세스를 고민 할 필요가 있음.

자체적으로 Guava 활용. 테스트 작성시 코드를

극히 간결하게 유지 할 수 있음.

메소드 단위 테스트가 불편

자바와 스칼라의 중간 어디쯤

Page 88: [1B4]안드로이드 동시성_프로그래밍

안드로이드 스튜디오에서 람다 사용

바이트 코드 조작을 통한 람다 사용

RetroLambda

• 암묵적 참조로 클래스 참조로 인한 메모리 문제가 없음

스튜디오의 기본기능인 폴딩도 괜찮지만,

람다 사용이 조금 더 편함

Page 89: [1B4]안드로이드 동시성_프로그래밍

함수형 프로그래밍

외부에서 건드릴 수 없음!

람다식이 함수형 프로그래밍은 절대 아님!

Page 90: [1B4]안드로이드 동시성_프로그래밍

함수형 프로그래밍의 특징

(x ∧ z) ∨ (y ∧ z) = (x ∨ y) ∧ z불 대수

x, y z 는 숫자이거나 집합

Page 91: [1B4]안드로이드 동시성_프로그래밍

함수형 프로그래밍의 특징

(λx.(λx.x)) y # λx.y

불 대수

람다 대수

(x ∧ z) ∨ (y ∧ z) = (x ∨ y) ∧ z

클래스가 함수라면! 람다 대수에 의해 연산 가능!

Page 92: [1B4]안드로이드 동시성_프로그래밍

Circle Progress

Page 93: [1B4]안드로이드 동시성_프로그래밍

RxJava

Callback => Observable

onDraw(Canvas canvas)

Observer<Canvas>

Page 94: [1B4]안드로이드 동시성_프로그래밍

RxJava

Subscriber<? super Canvas> canvasSubscriber; !@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvasSubscriber.onNext(canvas); }

Callback => Observable

RxJava를 통해 콜백을 마치 컬렉션 처럼 바꿔줌

Page 95: [1B4]안드로이드 동시성_프로그래밍

RxJava

Callback => Observable

Observable

onDraw(Canvas canvas)

Observer<Canvas>

이제 collection 처럼 사용가능

60fps

Page 96: [1B4]안드로이드 동시성_프로그래밍

RxJava

Callback => Observable

ObservableObserver<Canvas>

getDataFromLocalMemory() .skip(10) .take(5) .filter(...) .map(s -> s + " mapped" ) .forEach( print(s) )

getDataFromNetwork() .skip(10) .take(5) .filter(...) .map(s -> s + " mapped" ) .subscribe( print(s) )

Java 8’s Stream RxJava’s Observable

함수형 특징을 가진 언어는 다들 비슷비슷

Page 97: [1B4]안드로이드 동시성_프로그래밍

Callback => Observable

RxJava

sineValueObservable

drawCircle()Zip

canvasObservable

지퍼 맞음

Page 98: [1B4]안드로이드 동시성_프로그래밍

Callback => Observable

RxJava

sineValueObservable

drawCircle()Zip

canvasObservable

지퍼 맞음

Page 99: [1B4]안드로이드 동시성_프로그래밍

Callback => Observable

RxJava

sineValueObservable

drawCircle()Zip

canvasObservable

지퍼 맞음

Page 100: [1B4]안드로이드 동시성_프로그래밍

RxJava

Callback => Observable

canvasObservable

sineValueObservable

drawCircle()Zip

두 collection(obsavable)의

각각 요소를 하나씩 결합!

짝이 성사되면 그리기 수행!

Page 101: [1B4]안드로이드 동시성_프로그래밍

RxJava

Callback => Observable

canvasObservable

sineValueObservable

drawCircle()Zip

결과물 역시 Obserable

이므로, 추가적인 연산이

얼만든지 가능함~

Page 102: [1B4]안드로이드 동시성_프로그래밍

왜 RxJava?

Page 103: [1B4]안드로이드 동시성_프로그래밍

왜 RxJava?

Page 104: [1B4]안드로이드 동시성_프로그래밍

Reactive Extension

Page 105: [1B4]안드로이드 동시성_프로그래밍

ReactiveX

RxJs의 형제

Page 106: [1B4]안드로이드 동시성_프로그래밍

너무 어려워요…

함수형 프로그래밍은 어려운게 아닙니다.

!익숙해지는데 시간이 좀 걸릴 뿐입니다.

!Rx와 함수형이 만능은 아닙니다.

!칼퇴근을 보장하진 못하지만,

!품질은 높아지고, 스트레스는 낮아집니다.

!어렵게 느껴지면, 금요일 라 스칼라 코딩단에 구경오세요

!같이 고민해봐요.

! …안드로이드 개발자 항시 대기

!

Page 107: [1B4]안드로이드 동시성_프로그래밍

RxJAVA?!

Page 108: [1B4]안드로이드 동시성_프로그래밍

1. RxJava란?!2. RxJava(Thread, 이벤트 합성, 시간 관리, Subject, 예외 관리)!3. RxJava With MVVM!

RxJava

Page 109: [1B4]안드로이드 동시성_프로그래밍

RxJava란?

Excel - 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.

!!

A

B

C

1 2

10 20

= A1+A230

Page 110: [1B4]안드로이드 동시성_프로그래밍

RxJava란?

Excel - 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.

!!

A

B

C

1 2

10

= A1+A230

Page 111: [1B4]안드로이드 동시성_프로그래밍

RxJava란?

Excel - 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.

!!

A

B

C

1 2

10

= A1+A230

30

Page 112: [1B4]안드로이드 동시성_프로그래밍

RxJava란?

Excel - 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.

!!

A

B

C

1 2

10

= A1+A2

30

Page 113: [1B4]안드로이드 동시성_프로그래밍

RxJava란?

Excel - 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.

!!

A

B

C

1 2

10

= A1+A2

30

40

Page 114: [1B4]안드로이드 동시성_프로그래밍

Observable - 관측 가능한 값의 흐름를 나타내는 객체 (생산자)

Observer - 값의 흐름를 받는 객체 (소비자)!

RxJava - Observable, Observer란?

Button

Network

Keyboard

Alert

Image View

Text View

Image

Error

Input Text

Observable Observer

String

Byte[]

Click String

Visibility

ImageEvent

Page 115: [1B4]안드로이드 동시성_프로그래밍

Observable - 관측 가능한 값의 흐름를 나타내는 객체 (생산자) - subscribe 함수를 통해 구독이 가능하며, 구독자에게 값을 흐름을 알려준다.

!

Observer - 값의 흐름를 받는 객체 (소비자) - Observable의 값의 흐름에 따라 onNext, onError, onCompelete를 호출 받는다.

!

RxJava - Observable, Observer란?

OnNext OnComplete

OnError

Page 116: [1B4]안드로이드 동시성_프로그래밍

RxJava - Observable, Observer란?

eventSource.subscribe((event)-> { // some action. } );

Observable

Observer

Page 117: [1B4]안드로이드 동시성_프로그래밍

subscribe / unsubcribe - subscribe 를 통하여 Observable의 값의 변화를 구독하고,

unsubscribe를 통해 구독을 해지한다.

!!

RxJava - subscribe/unsubscribe

Observable!(Operation!

or!Producer)

Observable!(Operation) Observer

Button Function View

Page 118: [1B4]안드로이드 동시성_프로그래밍

subscribe / unsubcribe - subscribe 를 통하여 Observable의 값의 변화를 구독하고,

unsubscribe를 통해 구독을 해지한다.

!!

RxJava - subscribe/unsubscribe

Observable!(Operation!

or!Producer)

Observable!(Operation) Observer

subscribe()onSubscribe()Button Function View

Page 119: [1B4]안드로이드 동시성_프로그래밍

subscribe / unsubcribe - subscribe 를 통하여 Observable의 값의 변화를 구독하고,

unsubscribe를 통해 구독을 해지한다.

!!

RxJava - subscribe/unsubscribe

Observable!(Operation!

or!Producer)

Observable!(Operation) Observer

subscribe()onSubscribe()

onNext() onNext()

Button Function View

Page 120: [1B4]안드로이드 동시성_프로그래밍

subscribe / unsubcribe - subscribe 를 통하여 Observable의 값의 변화를 구독하고,

unsubscribe를 통해 구독을 해지한다.

!!

RxJava - subscribe/unsubscribe

Observable!(Operation!

or!Producer)

Observable!(Operation) Observer

subscribe()onSubscribe()

onNext() onNext(). . .

. . .

Button Function View

Page 121: [1B4]안드로이드 동시성_프로그래밍

subscribe / unsubcribe - subscribe 를 통하여 Observable의 값의 변화를 구독하고,

unsubscribe를 통해 구독을 해지한다.

!!

RxJava - subscribe/unsubscribe

Observable!(Operation!

or!Producer)

Observable!(Operation) Observer

subscribe()onSubscribe()

onNext() onNext()

onNext() onNext()

. . .. . .

Button Function View

Page 122: [1B4]안드로이드 동시성_프로그래밍

subscribe / unsubcribe - subscribe 를 통하여 Observable의 값의 변화를 구독하고,

unsubscribe를 통해 구독을 해지한다.

!!

RxJava - subscribe/unsubscribe

Observable!(Operation!

or!Producer)

Observable!(Operation) Observer

subscribe()onSubscribe()

onNext() onNext()

onNext() onNext()

onComplete() onComplete()

. . .. . .

Button Function View

Page 123: [1B4]안드로이드 동시성_프로그래밍

subscribe / unsubcribe - subscribe 를 통하여 Observable의 값의 변화를 구독하고,

unsubscribe를 통해 구독을 해지한다.

!!

RxJava - subscribe/unsubscribe

Observable!(Operation!

or!Producer)

Observable!(Operation) Observer

subscribe()onSubscribe()

onNext() onNext()

onNext() onNext()

onComplete() onComplete()

unsubscribe()unsubscribe()

. . .. . .

Button Function View

Page 124: [1B4]안드로이드 동시성_프로그래밍

키보드 입력값 출력 시나리오 - 키를 입력하면 TextView에 출력하는 시나리오

RxJava - map

EditText

Function

TextView

Page 125: [1B4]안드로이드 동시성_프로그래밍

키보드 입력값 출력 시나리오 - 키를 입력하면 TextView에 출력하는 시나리오

RxJava - map

EditText

Function

TextView

Text A

fun(x)

TextA-1

Page 126: [1B4]안드로이드 동시성_프로그래밍

키보드 입력값 출력 시나리오 - 키를 입력하면 TextView에 출력하는 시나리오

RxJava - map

EditText

Function

TextView

Text B

fun(x)

TextB-1

Text A

fun(x)

TextA-1

Page 127: [1B4]안드로이드 동시성_프로그래밍

키보드 입력값 출력 시나리오 - 키를 입력하면 TextView에 출력하는 시나리오

RxJava - map

EditText

Function

TextView

Text B

fun(x)

TextB-1

Text C

fun(x)

TextC-1

Text A

fun(x)

TextA-1

Page 128: [1B4]안드로이드 동시성_프로그래밍

map - 전달되는 값에 함수를 적용해서 새로운 값을 만들어냄

!!

RxJava - map

eventSource.map((value) -> {return fun(value);}) .subscribe((result) -> { ! // show result. });

Page 129: [1B4]안드로이드 동시성_프로그래밍

키보드 입력값 출력 시나리오 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오

RxJava - flatMap

EditText

Async Function

TextView

Page 130: [1B4]안드로이드 동시성_프로그래밍

키보드 입력값 출력 시나리오 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오

RxJava - flatMap

EditText

Async Function

TextView

Text A

Page 131: [1B4]안드로이드 동시성_프로그래밍

키보드 입력값 출력 시나리오 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오

RxJava - flatMap

EditText

Async Function

TextView

fun(x)

Text A

Page 132: [1B4]안드로이드 동시성_프로그래밍

키보드 입력값 출력 시나리오 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오

RxJava - flatMap

EditText

Async Function

TextView

fun(x)

TextA-1

Text A

Page 133: [1B4]안드로이드 동시성_프로그래밍

키보드 입력값 출력 시나리오 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오

RxJava - flatMap

EditText

Async Function

TextView

fun(x)

TextA-1

Text A Text B

Page 134: [1B4]안드로이드 동시성_프로그래밍

키보드 입력값 출력 시나리오 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오

RxJava - flatMap

EditText

Async Function

TextView

fun(x)

TextA-1

Text A

fun(x)

Text B

Page 135: [1B4]안드로이드 동시성_프로그래밍

키보드 입력값 출력 시나리오 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오

RxJava - flatMap

EditText

Async Function

TextView

fun(x)

TextA-1

Text A

fun(x)

TextB-1

Text B

Page 136: [1B4]안드로이드 동시성_프로그래밍

키보드 입력값 출력 시나리오 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오

RxJava - flatMap

EditText

Async Function

TextView

fun(x)

TextA-1

Text A

fun(x)

TextB-1

Text B Text C

Page 137: [1B4]안드로이드 동시성_프로그래밍

키보드 입력값 출력 시나리오 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오

RxJava - flatMap

EditText

Async Function

TextView

fun(x)

TextA-1

Text A

fun(x)

TextB-1

Text B

fun(x)

Text C

Page 138: [1B4]안드로이드 동시성_프로그래밍

키보드 입력값 출력 시나리오 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오

RxJava - flatMap

EditText

Async Function

TextView

fun(x)

TextA-1

Text A

fun(x)

TextB-1

Text B

fun(x)

TextC-1

Text C

Page 139: [1B4]안드로이드 동시성_프로그래밍

flatmap - 미래에 0개 ~ n개의 결과를 반환하는 함수를 적용한다.

!!

RxJava - flatMap

eventSource.flatMap((value) -> {return longlongFunc(value);}) .subscribe((Result) -> { ! // show result. ! });

Observable

Page 140: [1B4]안드로이드 동시성_프로그래밍

Thread 관리

Page 141: [1B4]안드로이드 동시성_프로그래밍

이미지 다운로드 시나리오 - 버튼을 클릭하면 이미지를 다운받아 표시하는 예제

RxJava - Scheduler

UI Thread

IO Thread

UI Thread

Click

Image

Image

Page 142: [1B4]안드로이드 동시성_프로그래밍

subscribeOn - 비동기 결과값을 가져오는 쓰레드를 결정한다

observeOn - 결과 값을 처리할 쓰레드를 결정한다.

RxJava - Scheduler

ClickEvents.flatMap((event) -> { return asyncDownloadImage(params) .subscribeOn(Schedulers.io()); }) .observeOn(AndroidSchedulers.mainThread()) .subscribe((image) -> { // show result. });

Page 143: [1B4]안드로이드 동시성_프로그래밍

observeOn - 결과 값을 처리할 쓰레드를 결정한다.

RxJava - Scheduler

Event

observeOn(MainThreadScheduler)

Main Thread

Thread

Page 144: [1B4]안드로이드 동시성_프로그래밍

subscribeOn - 비동기 결과값을 가져오는 쓰레드를 결정한다.

RxJava - Scheduler

subscribeOn(IOThreadScheduler)

IO Thread Event

IO Thread

Page 145: [1B4]안드로이드 동시성_프로그래밍

Schedulers.computation() - 단순 연산을 처리하는 Thread들의 Pool로 구성된 Scheduler.

!

Schedulers.io() - IO처리를 담당하는 Thread들의 Pool로 구성된 Scheduler.

- 필요에 따라 자동으로 Pool의 크기를 늘리거나 줄인다.

!

Schedulers.newThread() - 새로운 쓰레드를 만드는 Scheduler.

RxJava - Scheduler

Page 146: [1B4]안드로이드 동시성_프로그래밍

AndroidSchedulers.mainThread( ) - Android의 Main Thread에서 작업을 수행한다.

!

AndroidSchedulers.handlerThread(Handler handler) - 특정 Thread를 사용하는 Handler이용하는 Scheduler를 생성한다.

!

Schedulers.from(Executor executor) - 특정 Executor를 사용하는 Scheduler를 생성한다.

!!

RxJava - Scheduler

Page 147: [1B4]안드로이드 동시성_프로그래밍

이벤트 합성

Page 148: [1B4]안드로이드 동시성_프로그래밍

combineLatest - Observable 들의 이벤트들 중 가장 최신 이벤트 값을 합성해서 사용한다.

!

RxJava - combineLatest, merge

Observable.combineLatest(color, shape, new Func2<Color, Shape, Image>() { @Override public Image call(Color color, Shape shape) { return image.createFrom(color, shape); } } );

Page 149: [1B4]안드로이드 동시성_프로그래밍

combineLatest - Observable 들의 중 가장 최신의 이벤트 값을 합성한다.

!

RxJava - combineLatest, merge

Image

combineLatest( )Color

Shape

Page 150: [1B4]안드로이드 동시성_프로그래밍

combineLatest - Observable 들의 중 가장 최신의 이벤트 값을 합성한다.

!

RxJava - combineLatest, merge

1

Image

combineLatest( )Color

Shape

Page 151: [1B4]안드로이드 동시성_프로그래밍

combineLatest - Observable 들의 중 가장 최신의 이벤트 값을 합성한다.

!

RxJava - combineLatest, merge

1

Image

combineLatest( )Color

Shape

2

2

Page 152: [1B4]안드로이드 동시성_프로그래밍

combineLatest - Observable 들의 중 가장 최신의 이벤트 값을 합성한다.

!

RxJava - combineLatest, merge

1

Image

combineLatest( )Color

Shape

2

2

3

3

Page 153: [1B4]안드로이드 동시성_프로그래밍

combineLatest - Observable 들의 중 가장 최신의 이벤트 값을 합성한다.

!

RxJava - combineLatest, merge

1

Image

combineLatest( )Color

Shape

2

2

3

3 4

4

Page 154: [1B4]안드로이드 동시성_프로그래밍

merge - Observable 들의 이벤트들을 합성해서 사용한다.

!

RxJava - combineLatest, merge

Observable<Void> clickEvnets = Observable.merge(clickEventFromButtonA, clickEventFromButtonB);

Page 155: [1B4]안드로이드 동시성_프로그래밍

merge - Observable 들의 이벤트들을 합성해서 사용한다.

!

RxJava - combineLatest, merge

Login Event

merge( )Login Button

Enter Key

Page 156: [1B4]안드로이드 동시성_프로그래밍

merge - Observable 들의 이벤트들을 합성해서 사용한다.

!

RxJava - combineLatest, merge

Login Event

1

1

merge( )Login Button

Enter Key

Page 157: [1B4]안드로이드 동시성_프로그래밍

merge - Observable 들의 이벤트들을 합성해서 사용한다.

!

RxJava - combineLatest, merge

Login Event

1

1

merge( )Login Button

Enter Key

2

2

Page 158: [1B4]안드로이드 동시성_프로그래밍

merge - Observable 들의 이벤트들을 합성해서 사용한다.

!

RxJava - combineLatest, merge

Login Event

1

1

merge( )Login Button

Enter Key

3

32

2

Page 159: [1B4]안드로이드 동시성_프로그래밍

merge - Observable 들의 이벤트들을 합성해서 사용한다.

!

RxJava - combineLatest, merge

Login Event

1

1

merge( )Login Button

Enter Key

3

32

2 4

4

Page 160: [1B4]안드로이드 동시성_프로그래밍

시간 관리

Page 161: [1B4]안드로이드 동시성_프로그래밍

예제) throttleWithTimeout - 자동 완성 기능

!

RxJava - Time

// 기본 변수 설정 final PublishSubject<String> inputText = PublishSubject.create(); TextView autoCompleteTextView = (TextView) findViewById(R.id.auto_complete_text); !// 1초동안 사용자 입력이 없는 경우 네트워크에서 값을 받아와서 갱신 inputText.throttleWithTimeout(1, TimeUnit.SECONDS) .observeOn(Schedulers.io()) .flatMap(new GetAutocompleteKeywordsFromNetwork()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new SetTextAction(autoCompleteTextView));

Page 162: [1B4]안드로이드 동시성_프로그래밍

delay - 모든 이벤트를 주어진 시간만큼 지연한다.

!

RxJava - Time

Observer

delay( )

Page 163: [1B4]안드로이드 동시성_프로그래밍

delay - 모든 이벤트를 주어진 시간만큼 지연한다.

!

RxJava - Time

1

Observer

delay( )

Page 164: [1B4]안드로이드 동시성_프로그래밍

delay - 모든 이벤트를 주어진 시간만큼 지연한다.

!

RxJava - Time

1

Observer 1

delay( )

Page 165: [1B4]안드로이드 동시성_프로그래밍

delay - 모든 이벤트를 주어진 시간만큼 지연한다.

!

RxJava - Time

21

Observer 1

delay( )

Page 166: [1B4]안드로이드 동시성_프로그래밍

delay - 모든 이벤트를 주어진 시간만큼 지연한다.

!

RxJava - Time

21

Observer 1 2

delay( )

Page 167: [1B4]안드로이드 동시성_프로그래밍

delay - 모든 이벤트를 주어진 시간만큼 지연한다.

!

RxJava - Time

21 3

Observer 1 2

delay( )

Page 168: [1B4]안드로이드 동시성_프로그래밍

delay - 모든 이벤트를 주어진 시간만큼 지연한다.

!

RxJava - Time

21 3

Observer 1 2 3

delay( )

Page 169: [1B4]안드로이드 동시성_프로그래밍

throttleFirst - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.

!

RxJava - Time

Observer

throttleFirst( )

Page 170: [1B4]안드로이드 동시성_프로그래밍

throttleFirst - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.

!

RxJava - Time

Observer

throttleFirst( )

1

1

Page 171: [1B4]안드로이드 동시성_프로그래밍

throttleFirst - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.

!

RxJava - Time

Observer

throttleFirst( )

1

1

Page 172: [1B4]안드로이드 동시성_프로그래밍

throttleFirst - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.

!

RxJava - Time

Observer

throttleFirst( )

1

1 2

Page 173: [1B4]안드로이드 동시성_프로그래밍

throttleFirst - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.

!

RxJava - Time

Observer

throttleFirst( )

1

1

3

32

Page 174: [1B4]안드로이드 동시성_프로그래밍

throttleFirst - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.

!

RxJava - Time

Observer

throttleFirst( )

1

1

3

32

Page 175: [1B4]안드로이드 동시성_프로그래밍

throttleFirst - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.

!

RxJava - Time

Observer

throttleFirst( )

1

1

3

32 4

Page 176: [1B4]안드로이드 동시성_프로그래밍

throttleFirst - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.

!

RxJava - Time

Observer

throttleFirst( )

1

1

3

3 5

5

2 4

Page 177: [1B4]안드로이드 동시성_프로그래밍

throttleFirst - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.

!

RxJava - Time

Observer

throttleFirst( )

1

1

3

3 5

5

2 4

Page 178: [1B4]안드로이드 동시성_프로그래밍

throttleWithTimeout - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.

!

RxJava - Time

Observer

throttleWithTimeout( )

Page 179: [1B4]안드로이드 동시성_프로그래밍

throttleWithTimeout - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.

!

RxJava - Time

Observer

throttleWithTimeout( )

1

Page 180: [1B4]안드로이드 동시성_프로그래밍

throttleWithTimeout - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.

!

RxJava - Time

Observer

throttleWithTimeout( )

1

Page 181: [1B4]안드로이드 동시성_프로그래밍

throttleWithTimeout - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.

!

RxJava - Time

Observer

throttleWithTimeout( )

1

1

Page 182: [1B4]안드로이드 동시성_프로그래밍

throttleWithTimeout - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.

!

RxJava - Time

Observer

throttleWithTimeout( )

1 2

1

Page 183: [1B4]안드로이드 동시성_프로그래밍

throttleWithTimeout - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.

!

RxJava - Time

Observer

throttleWithTimeout( )

1 2

1

Page 184: [1B4]안드로이드 동시성_프로그래밍

throttleWithTimeout - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.

!

RxJava - Time

Observer

throttleWithTimeout( )

1 2 3

1

Page 185: [1B4]안드로이드 동시성_프로그래밍

throttleWithTimeout - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.

!

RxJava - Time

Observer

throttleWithTimeout( )

1 2 3

1

Page 186: [1B4]안드로이드 동시성_프로그래밍

throttleWithTimeout - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.

!

RxJava - Time

Observer

throttleWithTimeout( )

1 2 43

1

Page 187: [1B4]안드로이드 동시성_프로그래밍

throttleWithTimeout - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.

!

RxJava - Time

Observer

throttleWithTimeout( )

1 2 43

1

Page 188: [1B4]안드로이드 동시성_프로그래밍

throttleWithTimeout - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.

!

RxJava - Time

Observer

throttleWithTimeout( )

1 2 43

1 4

Page 189: [1B4]안드로이드 동시성_프로그래밍

Subject

Page 190: [1B4]안드로이드 동시성_프로그래밍

BehaviorSubject를 사용한 SharedPreferences 예제!!

RxJava - Subject(Observable + Observer)

final String KEY = “key_user_id”; ! // User ID 변수 선언 BehaviorSubject<String> userId = BehaviorSubject.create(); ! // SharePreference 에서 Background Thread로 값을 읽어온다. readFromSharedPreferences(KEY, "").subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(userId); ! // userId 값이 변경되면 SharePreference에 비동기로 값을 기록한다. userId.distinctUntilChanged() .observeOn(Schedulers.io()) .subscribe(new WriteToSharedPreferences(KEY));

Page 191: [1B4]안드로이드 동시성_프로그래밍

BehaviorSubject!!!

RxJava - Subject(Observable + Observer)

BehaviorSubject

Observer1

Observer2

Page 192: [1B4]안드로이드 동시성_프로그래밍

BehaviorSubject!!!

RxJava - Subject(Observable + Observer)

1

BehaviorSubject

Observer1

Observer2

Page 193: [1B4]안드로이드 동시성_프로그래밍

BehaviorSubject!!!

RxJava - Subject(Observable + Observer)

1su

bscribe()

BehaviorSubject

Observer1

Observer2

Page 194: [1B4]안드로이드 동시성_프로그래밍

BehaviorSubject!!!

RxJava - Subject(Observable + Observer)

1su

bscribe()

1

BehaviorSubject

Observer1

Observer2

Page 195: [1B4]안드로이드 동시성_프로그래밍

BehaviorSubject!!!

RxJava - Subject(Observable + Observer)

2

21su

bscribe()

1

BehaviorSubject

Observer1

Observer2

Page 196: [1B4]안드로이드 동시성_프로그래밍

BehaviorSubject!!!

RxJava - Subject(Observable + Observer)

2

21su

bscribe()

1

subs

cribe()

BehaviorSubject

Observer1

Observer2

Page 197: [1B4]안드로이드 동시성_프로그래밍

BehaviorSubject!!!

RxJava - Subject(Observable + Observer)

2

21su

bscribe()

1

2

subs

cribe()

BehaviorSubject

Observer1

Observer2

Page 198: [1B4]안드로이드 동시성_프로그래밍

BehaviorSubject!!!

RxJava - Subject(Observable + Observer)

2

21su

bscribe()

1

2

3

3

3

subs

cribe()

BehaviorSubject

Observer1

Observer2

Page 199: [1B4]안드로이드 동시성_프로그래밍

PublishSubject!!

RxJava - Subject(Observable + Observer)

PublishSubject

Observer1

Observer2

Page 200: [1B4]안드로이드 동시성_프로그래밍

PublishSubject!!

RxJava - Subject(Observable + Observer)

1

PublishSubject

Observer1

Observer2

Page 201: [1B4]안드로이드 동시성_프로그래밍

PublishSubject!!

RxJava - Subject(Observable + Observer)

1su

bscribe()

PublishSubject

Observer1

Observer2

Page 202: [1B4]안드로이드 동시성_프로그래밍

PublishSubject!!

RxJava - Subject(Observable + Observer)

2

21su

bscribe()

PublishSubject

Observer1

Observer2

Page 203: [1B4]안드로이드 동시성_프로그래밍

PublishSubject!!

RxJava - Subject(Observable + Observer)

2

21su

bscribe()

subs

cribe()

PublishSubject

Observer1

Observer2

Page 204: [1B4]안드로이드 동시성_프로그래밍

PublishSubject!!

RxJava - Subject(Observable + Observer)

2

21su

bscribe()

3

3

3

subs

cribe()

PublishSubject

Observer1

Observer2

Page 205: [1B4]안드로이드 동시성_프로그래밍

Replay Subject!!

RxJava - Subject(Observable + Observer)

ReplaySubject

Observer1

Observer2

Page 206: [1B4]안드로이드 동시성_프로그래밍

Replay Subject!!

RxJava - Subject(Observable + Observer)

1

ReplaySubject

Observer1

Observer2

Page 207: [1B4]안드로이드 동시성_프로그래밍

Replay Subject!!

RxJava - Subject(Observable + Observer)

1su

bscribe()

ReplaySubject

Observer1

Observer2

Page 208: [1B4]안드로이드 동시성_프로그래밍

Replay Subject!!

RxJava - Subject(Observable + Observer)

1su

bscribe()

ReplaySubject

Observer1

Observer21

Page 209: [1B4]안드로이드 동시성_프로그래밍

Replay Subject!!

RxJava - Subject(Observable + Observer)

2

21su

bscribe()

ReplaySubject

Observer1

Observer21

Page 210: [1B4]안드로이드 동시성_프로그래밍

Replay Subject!!

RxJava - Subject(Observable + Observer)

2

21su

bscribe()

subs

cribe()

ReplaySubject

Observer1

Observer21

Page 211: [1B4]안드로이드 동시성_프로그래밍

Replay Subject!!

RxJava - Subject(Observable + Observer)

2

21su

bscribe()

subs

cribe()

ReplaySubject

Observer1

Observer21

1

Page 212: [1B4]안드로이드 동시성_프로그래밍

Replay Subject!!

RxJava - Subject(Observable + Observer)

2

21su

bscribe()

subs

cribe()

ReplaySubject

Observer1

Observer21

1 2

Page 213: [1B4]안드로이드 동시성_프로그래밍

Replay Subject!!

RxJava - Subject(Observable + Observer)

2

21su

bscribe()

subs

cribe()

ReplaySubject

Observer1

Observer21

1 2

3

3

3

Page 214: [1B4]안드로이드 동시성_프로그래밍

예외 관리

Page 215: [1B4]안드로이드 동시성_프로그래밍

doOnError - 실패한 경우, 예외를 처리하는 기능을 수행할 수 있습니다.

!

RxJava - Error Handling

GetDataFromNetwork() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnError((e) -> {showError(e);}) .subscribe((img) -> {showImage(img);})

1Observer

1 X

Page 216: [1B4]안드로이드 동시성_프로그래밍

doOnError - 실패한 경우, 예외를 처리하는 기능을 수행할 수 있습니다.

!

RxJava - Error Handling

GetDataFromNetwork() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnError((e) -> {showError(e);}) .subscribe((img) -> {showImage(img);})

1Observer

1 X

Error Handling

Page 217: [1B4]안드로이드 동시성_프로그래밍

retry - 실패한 경우 자동으로 재시도 합니다.

!

RxJava - Error Handling

GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry()

Observer

retry()

Page 218: [1B4]안드로이드 동시성_프로그래밍

retry - 실패한 경우 자동으로 재시도 합니다.

!

RxJava - Error Handling

GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry()

Observer

retry()1

1

Page 219: [1B4]안드로이드 동시성_프로그래밍

retry - 실패한 경우 자동으로 재시도 합니다.

!

RxJava - Error Handling

GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry()

Observer

retry()1

1 X

Page 220: [1B4]안드로이드 동시성_프로그래밍

retry - 실패한 경우 자동으로 재시도 합니다.

!

RxJava - Error Handling

GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry()

Observer

retry()1

1 X

Page 221: [1B4]안드로이드 동시성_프로그래밍

retry - 실패한 경우 자동으로 재시도 합니다.

!

RxJava - Error Handling

GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry()

Observer

retry()1

1 X

3

3

Page 222: [1B4]안드로이드 동시성_프로그래밍

retry(int n) - 실패한 경우 자동으로 n회 재시도 합니다.

!

RxJava - Error Handling

GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry(1)

Observer

retry(1)

Page 223: [1B4]안드로이드 동시성_프로그래밍

retry(int n) - 실패한 경우 자동으로 n회 재시도 합니다.

!

RxJava - Error Handling

GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry(1)

Observer

retry(1)1

1

Page 224: [1B4]안드로이드 동시성_프로그래밍

retry(int n) - 실패한 경우 자동으로 n회 재시도 합니다.

!

RxJava - Error Handling

GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry(1)

Observer

retry(1)1

1 X

Page 225: [1B4]안드로이드 동시성_프로그래밍

retry(int n) - 실패한 경우 자동으로 n회 재시도 합니다.

!

RxJava - Error Handling

GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry(1)

Observer

retry(1)1

1 X

Page 226: [1B4]안드로이드 동시성_프로그래밍

retry(int n) - 실패한 경우 자동으로 n회 재시도 합니다.

!

RxJava - Error Handling

GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry(1)

Observer

retry(1)1

1 X

2

2

Page 227: [1B4]안드로이드 동시성_프로그래밍

retry(int n) - 실패한 경우 자동으로 n회 재시도 합니다.

!

RxJava - Error Handling

GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry(1)

Observer

retry(1)1

1 X

2

2 X

X

Page 228: [1B4]안드로이드 동시성_프로그래밍

retryWhen(Observable) - 실패한 경우 자동으로 재시도 합니다.

!

RxJava - Error Handling

Observer

retryWhen()

Page 229: [1B4]안드로이드 동시성_프로그래밍

retryWhen(Observable) - 실패한 경우 자동으로 재시도 합니다.

!

RxJava - Error Handling

Observer

retryWhen()

1

1

Page 230: [1B4]안드로이드 동시성_프로그래밍

retryWhen(Observable) - 실패한 경우 자동으로 재시도 합니다.

!

RxJava - Error Handling

Observer

retryWhen()

1

1 X

Page 231: [1B4]안드로이드 동시성_프로그래밍

retryWhen(Observable) - 실패한 경우 자동으로 재시도 합니다.

!

RxJava - Error Handling

Observer

retryWhen()

1

1 X

delay(3, SECODS)

Page 232: [1B4]안드로이드 동시성_프로그래밍

retryWhen(Observable) - 실패한 경우 자동으로 재시도 합니다.

!

RxJava - Error Handling

Observer

retryWhen()

1

1 X

delay(3, SECODS)

Page 233: [1B4]안드로이드 동시성_프로그래밍

retryWhen(Observable) - 실패한 경우 자동으로 재시도 합니다.

!

RxJava - Error Handling

Observer

retryWhen()

1

1 X

3

3

delay(3, SECODS)

Page 234: [1B4]안드로이드 동시성_프로그래밍

retryWhen(Observable) - 실패한 경우 자동으로 재시도 합니다.

!

RxJava - Error Handling

Observer

retryWhen()

1

1 X

3

3

delay(3, SECODS)

!GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retryWhen((observable) -> { // 3초마다 재시도 return observable.delay(3, TimeUnit.SECONDS); })

Page 235: [1B4]안드로이드 동시성_프로그래밍

MVVM With RxJava

Page 236: [1B4]안드로이드 동시성_프로그래밍

Loading Indicator 예제버튼을 클릭하면 다운로드가 완료될 때까지 Loading indicator를 표시한다.

!

RxJava - MVVM

! // 버튼 클릭 이벤트 Observable<Void> btnClickEvent = … ! Observable.merge( btnClickEvent.map((event) -> {return true;}, btnClickEvent.flatMap((event)-> { return downloadFunction().subscribeOn(Schedulers.io()) }).map((event) -> {return false;}) .observeOn(AndroidSchedulers.main()) ! .subscribe((isVisible) -> { v.setVisibility(isVisible ? View.VISIBLE : View.GONE); )}

Page 237: [1B4]안드로이드 동시성_프로그래밍

Loading Indicator 예제버튼을 클릭하면 다운로드가 완료될 때까지 Loading indicator를 표시한다.

!

RxJava - MVVM

! // 버튼 클릭 이벤트 Observable<Void> btnClickEvent = … ! Observable.merge( btnClickEvent.map((event) -> {return true;}, btnClickEvent.flatMap((event)-> { return downloadFunction().subscribeOn(Schedulers.io()) }).map((event) -> {return false;}) .observeOn(AndroidSchedulers.main()) ! .subscribe((isVisible) -> { v.setVisibility(isVisible ? View.VISIBLE : View.GONE); )}

View Model

View

Page 238: [1B4]안드로이드 동시성_프로그래밍

RxJava - MVVM

User Info

Login Info

Profile Image

Alert

Image View

Text View

Image

Error

Input Text

Model View

Image

String

String String

Visibility

Image

Event

View Model

운영체제에

의존적운영체제에

독립적

Page 239: [1B4]안드로이드 동시성_프로그래밍

RxJava - MVVM

User Info

Login Info

Profile Image

Alert

Image View

Text View

Image

Error

Input Text

Model View

Image

String

String String

Visibility

Image

Event

View Model

재사용이

어려움재사용이

원활함

Page 240: [1B4]안드로이드 동시성_프로그래밍

RxJava - MVVM

User Info

Login Info

Profile Image

Alert

Image View

Text View

Image

Error

Input Text

Model View

Image

String

String String

Visibility

Image

Event

View Model

테스트 불

가능 코드테스트 가능 코드

연결 코드

Page 241: [1B4]안드로이드 동시성_프로그래밍

결론

Page 242: [1B4]안드로이드 동시성_프로그래밍

프로그램의 일관성을 유지하는 통일된 방식이 필요 - Event, Thread, 시간, Exception을 처리하기에는 Callback은 조합이 어렵다.

- 그러므로 개개인이 각각의 방식으로 조합하여 복잡성이 증대된다.

!!

단순 객체지향으로는 큰 프로그램을 만들기 어렵다. - 객체지향은 내부의 상세한 구현을 숨긴다.

- 이로인해 잘 만들지 않으면 기대와 다른 동작들로 인해 복잡도가 증가한다.

- 이를 해결하기 위해 객체가 객체를 감싸고 또다시 감싸는 등의 문제가 발생한다.

!!

왜 Reactive Programming 인가?

Page 243: [1B4]안드로이드 동시성_프로그래밍

프로그램의 일관성을 유지하는 통일된 방식이 필요 - Event, Thread, 시간, Exception을 처리하기에는 Callback은 조합이 어렵다.

- 그러므로 개개인이 각각의 방식으로 조합하여 복잡성이 증대된다.

!!

단순 객체지향으로는 큰 프로그램을 만들기 어렵다. - 객체지향은 내부의 상세한 구현을 숨긴다.

- 이로인해 잘 만들지 않으면 기대와 다른 동작들로 인해 복잡도가 증가한다.

- 이를 해결하기 위해 객체가 객체를 감싸고 또다시 감싸는 등의 문제가 발생한다.

!!

왜 Reactive Programming 인가?

통일된 방식으로 Event, Thread, Time, Exception을 처리할 수 있는 방법 제공

Page 244: [1B4]안드로이드 동시성_프로그래밍

프로그램의 일관성을 유지하는 통일된 방식이 필요 - Event, Thread, 시간, Exception을 처리하기에는 Callback은 조합이 어렵다.

- 그러므로 개개인이 각각의 방식으로 조합하여 복잡성이 증대된다.

!!

단순 객체지향으로는 큰 프로그램을 만들기 어렵다. - 객체지향은 내부의 상세한 구현을 숨긴다.

- 이로인해 잘 만들지 않으면 기대와 다른 동작들로 인해 복잡도가 증가한다.

- 이를 해결하기 위해 객체가 객체를 감싸고 또다시 감싸는 등의 문제가 발생한다.

!!

왜 Reactive Programming 인가?

통일된 방식으로 Event, Thread, Time, Exception을 처리할 수 있는 방법 제공

외부에 제공할 수 있는 읽기 전용의 Observable을 제공하며 내용을 감추지

않아도 됨

Page 245: [1B4]안드로이드 동시성_프로그래밍

보다 테스트하기 쉬운 구조가 필요하다. - 일반적인 구현에서는 가장 내부 깊은 곳에 View, Activity 등이 존재한다.

- 이로 인해 테스트에서 View를 제거하지 못해 테스트가 힘들어진다.

왜 Reactive Programming 인가?

Page 246: [1B4]안드로이드 동시성_프로그래밍

보다 테스트하기 쉬운 구조가 필요하다. - 일반적인 구현에서는 가장 내부 깊은 곳에 View, Activity 등이 존재한다.

- 이로 인해 테스트에서 View를 제거하지 못해 테스트가 힘들어진다.

왜 Reactive Programming 인가?

MVVM의 구조를 활용하여 OS 종속적인 부분을 최대한 배제하고 테스트할 수 있음

Page 247: [1B4]안드로이드 동시성_프로그래밍

감사합니다.