SlideShare a Scribd company logo
1 of 247
Download to read offline
안드로이드 동시성 프로그래밍 - 
RxJava를 활용한 Functional 
Reactive Programming 
최정열 / Sivaworks / 라 스칼라 코딩단䯽 
email: myeesan@gmail.com䯽 
조현태 / Line + / 라 스칼라 코딩단䯽 
email: waynejo1024@gmail.com
오늘의 목표
오늘의 목표 
함수형 프로그래밍에 한 번 관심을 가져보시는 것은 어떨까요?䯽 
! 
함수형을 프로그래밍을 익히는 것이 가장 큰 도전…䯽 
! 
더 어려운 부분은 절차형과 함수형에서 효율적인 방법을 선택하는 것!䯽 
! 
라 스칼라 코딩단: https://groups.google.com/forum/#!forum/scala-korea䯽 
! 
샘플 저장소: https://github.com/orgs/FridayCoders/dashboard (업데이트 예정)䯽 
!
안드로이드 동시성 프로그래밍 
1. Plain Old Java Concurrent Programming䯽 
2. 생명주기와 동시성 프로그래밍䯽 
3. Sequencial Tasks & Parellel Tasks䯽 
4. 람다 & 함수형 프로그래밍䯽
동시성 관련䯽 
클래스 & 패키지
Concurrent Programming 
Android Concurrent Programming 
Thread 
concurrent package 
Handler 
AsyncTask 
Service 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
AndroidAnnotations 
Guava 
greenrobot/EventBus 
otto
Concurrent Programming 
Thread 
new Thread() { 
@Override public void run() { 
URL url = new URL(strUrl); 
HttpURLConnection urlConnection = ... 
urlConnection.connect(); 
iStream = urlConnection.getInputStream(); 
bitmap = BitmapFactory.decodeStream(iStream); 
} 
}.start(); 
Background
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
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
Thread class 
예외는 백그라운드에서 발생하지만, 메시지는 UI쓰레드로… 
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
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){ 
// ... 
} 
...
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) { 
... 
} 
보기 편하게 람다식으로…
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? 
! 
구현을 들여다 보지 않으면 모르겠는걸?
Thread class 
현재 쓰레드에서 메소드 호출과 UI쓰레드 호출을 비교 
Bitmap downloadUrl(String strUrl) { 
... 
handleException(e, ()-> “다운로드 실패” ); 
} 
! 
! 
! 
// 1 
void handleException(Exception e, OnError onError) { 
runOnUiThread(new Runnable(){ 
void run(){ 
log.d(onError.call());} 
} 
UI 쓰레드 
로깅은 백그라운드에서 처리해도 되는데, 
UI 쓰레드에서 호출하는건 낭비 닐까? 
} 
! 
// 2 
void handleException(Exception e, OnError onError) { 
log.d(onError.call()); 
} 현재 쓰레드 (Background)
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(); 
} 
뷰를 조작하는 코드를 전달 하면?
Thread class 
CalledFromWrongThreadException 
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 쓰레드 외에서는 뷰를 조작 할 수 없음!
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(); 
} 
모든 메소드의 이름을 이렇게 짓는 것은 무리야!
Life Cycle 
생명주기와 쓰레드
생명주기와 쓰레드 
쓰레드를 시작했으면 독립적으로 존재 
UI Thread Activity A 
onDestroy() 
Background Thread 
Activity B 
Activity A가 종료 되어도 쓰레드는 독립적으로 살아 있음
생명주기와 쓰레드 
Inner class 사용시 메무리 누수 
UI Thread 
Activity A 
Reference 
Background Thread 
쓰레드가 암묵적으로 참조하고 
있어서, onDestroy()가 호출 된 
후에도, GC되지 않음! 
Activity B 
onDestroy() 
성능 저하, 메모리 낭비 
Inner class로 쓰레드를 만들면 암북적으로 액티비티를 참조
생명주기와 쓰레드 
쓰레드를 종료 시킬 깔끔한 방법의 필요성 
onStop() onDestroy() 
UI Thread Activity A 
Background Thread 
어디선간 쓰레드를 종료 해야겠네! 
어떻게 종료 시키지? 
interrupt? 
또, try ~ catch ~ final?
생명주기와 쓰레드 
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 작업이 끝나면 콜백을 
통해 결과를 전달~
생명주기와 쓰레드 
예외 발생 
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요소에는 직접 처리 할 수 없으므로 
콜백 메소드를 추가.
Concurrent Programming 
Android Concurrent Programming 
Thread 
concurrent package 
Handler 
AsyncTask 
Service 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
Executor + Thread pool + Future … 
Thread 보다 추상화된 제어가 가능! 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
AndroidAnnotations 
Guava 
greenrobot/EventBus 
otto
Concurrent Programming 
Android Concurrent Programming 
Thread 
concurrent package 
Handler 
AsyncTask 
Service 
안드로이드의 UI Thread를 관리하는 놈. 
Looper와 함께 사용하고, Looper는 메시지 
큐를 가지고 있어서 순차 실행을 보장! 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
AndroidAnnotations 
Guava 
greenrobot/EventBus 
otto
Concurrent Programming 
Android Concurrent Programming 
Thread 
concurrent package 
Handler 
AsyncTask 
Service 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
Handler + 탬플릿 메소드 패턴 
AndroidAnnotations 
Guava 
greenrobot/EventBus 
otto
AsyncTask class 
다운로드 + Ui + 예외 처리 (?) 
@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 쓰레드
AsyncTask class 
다운로드 + Ui + 예외 처리 (?) 
@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); 
} 
백그라운드 쓰레드
AsyncTask class 
다운로드 + Ui + 예외 처리 (?) 
@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로 어떻 
게 전달하지?
Concurrent Programming 
Android Concurrent Programming 
Thread 
concurrent package 
Handler 
AsyncTask 
Service 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
AndroidAnnotations 
Guava 
greenrobot/EventBus 
otto 
액티비티의 생명 주기로 부터 
영향을 받지 않음!
Concurrent Programming 
Android Concurrent Programming 
Thread 
concurrent package 
Handler 
AsyncTask 
Service 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
AndroidAnnotations 
Guava 
커서관리 방법 없고, 
greenrobot/EventBus 
AsyncTask와 문제점 공유 
otto
Concurrent Programming 
Android Concurrent Programming 
Thread 
concurrent package 
Handler 
AsyncTask 
Service 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
AndroidAnnotations 
Guava 
허니컴 이후 등장. compat을 이용해서 이전에도 
사용이 가능하며 생명주기 변경시 스스로 처리함 
단, ContentProvider 외에는 사용이 어려움 
greenrobot/EventBus 
otto
동시성 관련䯽 
라이브러리
Concurrent Programming 
Third Party Libraries 
Thread 
concurrent package 
Handler 
AsyncTask 
Service 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
AndroidAnnotations 
Guava 
greenrobot/EventBus 
otto 
네트워크, 이미지 
Callback 기반
Concurrent Programming 
Third Party Libraries 
Thread 
concurrent package 
Handler 
AsyncTask 
Service 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
AndroidAnnotations 
Guava 
greenrobot/EventBus 
otto 
동기, 비동기 (async) 지원 
RxJava의 Observable 지원
Concurrent Programming 
Third Party Libraries 
Thread 
concurrent package 
Handler 
AsyncTask 
Service 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
AndroidAnnotations 
Guava 
greenrobot/EventBus 
otto
Concurrent Programming 
Third Party Libraries 
Thread 
concurrent package 
Handler 
AsyncTask 
Service 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
AndroidAnnotations 
Guava 
greenrobot/EventBus 
otto 
Future
Concurrent Programming 
Third Party Libraries 
Thread 
concurrent package 
Handler 
AsyncTask 
Service 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
AndroidAnnotations 
Guava 
greenrobot/EventBus 
otto 
@Background 어노테이션 
내부적으로 ScheduledThreadPool을 활용
Concurrent Programming 
Third Party Libraries 
Thread 
concurrent package 
Handler 
AsyncTask 
Service 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
AndroidAnnotations 
Guava 
greenrobot/EventBus 
otto 
ListenableFuture
Concurrent Programming 
Third Party Libraries 
Thread 
concurrent package 
Handler 
AsyncTask 
Service 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
AndroidAnnotations 
Guava 
greenrobot/EventBus 
otto 
이벤트 버스 
RxJava로 대체 할 수 있음
Concurrent Programming 
Third Party Libraries 
Thread 
애플리케이션의 설계가 라이브러리 인터페이스에 의존적이 되는 것을 주의! 
저마다 Http client, 이미지 캐싱, ThreadPool 관리 서로 다른 정책과 인터페이 
concurrent package 
Handler 
AsyncTask 
Service 
스를 가지고 있으므로, 중복 설정 및 불필요한 추상화를 주의! 
AsyncQueryHandler 
Loader 
Volley 
OkHttp, Retrofit, Picasso 
AndroidUniversalImageLoader 
AndroidAsync(Http), ION 
AndroidAnnotations 
Guava 
greenrobot/EventBus 
otto
Concurrent Programming 
Android Event Sources 
KEY & TOUCH 
ACCELEROMETER 
GRAVITY 
GYROSCOPE 
LIGHT 
MAGNETIC 
ORIENTATION 
LOCATION 
PRESSURE
Parallel tasks䯽 
Concurrently executing tasks 
멀티 태스크 
Sequencial tasks䯽 
One after another 
Request 
Task A 
Task B 
Task C 
Request 
반드시 순서대로 실행 되어 
야 하는 태스크 묶음 
Task A Task B Task C 
Result Result
흔한 로그인 시나리오 
1. Auth 
2. Token 
3. Login 
4. Result 
5. Request 
6. Image 
Login with 
순서대로 실행 되어야 함
Sequencial tasks 
순서를 갖는 작업들 
UI Thread Req Resp 
Background TASK A TASK B TASK C
Sequencial tasks 
특히, Volley 
Callback 만을 지원하는 라이브러리 사용시 
불필요한 UI 쓰레드 점유 
UI Thread Req Resp 
Background TASK A TASK B TASK C
Sequencial tasks 
구현 방식 
• Nested Callbacks 
• Future combination 
• SingleThreadExecutor 
• Handler + Looper 
Callback hell을 해결 할 수 있지만, 
소스 네비게이션시 라인 점프는 늘어 날 수 있음. 
하나의 쓰레드와 Task를 결합. 단, 오류 처리는 쉽지 않음 
직접 워커를 만듦 커스텀 콜백 인터페이스를 정의 해야 함
흔한 로그인 시나리오 
Callback hell 
requestFacebookLogin(new Callback() { 
public void onSuccess(Result result) { 
... 
} 
});
흔한 로그인 시나리오 
Callback hell 
requestFacebookLogin(new Callback() { 
public void onSuccess(Result result) { 
String facebookId = result.getFacebookId(); 
requestLogin(facebookId, new Callback() { 
... 
}); 
} 
});
흔한 로그인 시나리오 
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배씩 증가;;
흔한 로그인 시나리오 
재시도 전략 
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에 예외가 발생한 작업을 재시도 하고 싶을 땐? 
@#!%
흔한 로그인 시나리오 
페이스북 로그인 > 앱 서버 로그인 > 초기 데이터 요청 > 오류 처리 
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를 통해 유저에게 알리고 싶은데, 
“나는 누구 여긴 어디?”
Parallel tasks䯽 
Concurrently executing tasks 
멀티 태스크 
Sequencial tasks䯽 
One after another 
태스크간의 의존성이 없어, 동시 
에 실행 될 수 있음. 
그러나, 우리는 UI 프로그래머 
Request 
Task A 
Task B 
Task C 
Request 
Task A Task B Task C 
Result Result
흔한 컨텐츠 공유 시나리오
흔한 컨텐츠 공유 시나리오 
1. Req 
1. Req 
1. Req 
1. Req
흔한 컨텐츠 공유 시나리오 
1. Req 
2. Resp 
1. Req 
2. Resp 
1. Req 
2. Resp 
1. Req 
2. Resp
Parellel Tasks 
동시에 수행 해야 하는 작업들 
작업이 끝나는 시간은 모두 다를 수 있음. 
모든 작업이 끝났을 때, UI에 반영하고 싶은데… 
UI Thread Login Data 
Thread A Data 
latency 
Thread B 
Thread C 
Data latency 
Data latency
흔한 컨텐츠 공유 시나리오 
1. Req 
2. Resp 
1. Req 
2. Resp 
1. Req 
2. Resp 
1. Req 
2. Resp 
작업이 완료䯽 
되었습니다.
Parellel Tasks 
구현 방식 
각각의 태스크를 수행하고 flag를 통해 결과를 취합 
• Creating Multiple Threads 
• CountDownLatch, MultiThreadExecutor (Thread Pool) 
요청이 많은 경우 쓰레드 풀을 이용 
concurrent 패키지의 CountDownLatch
Composed Tasks 
순차 + 병렬 
Request 
Task A 
Task B 
Task C 
Task A Task B Task B 
Result 
앱을 통해 사진과 글을 포스팅 
(순차 태스크) 
포스팅한 글을 SNS에 공유 
(병렬 태스크)
이런거 없나? 
어떤 데이터가 있는데…䯽 
어떤 쓰레드에서 수행하고,䯽 
필요한 데이터만 걸러내고,䯽 
데이터를 어떻게 변환하고,䯽 
오류 발생시에는 어떻게 대응할지,䯽 
어떤 쓰레드에서 결과를 받을지,䯽 
시작하면,䯽 
! 
필요한 경우 취소 할 수 있어야 한다.䯽 
! 
테스트도 쉬워야겠고!䯽 
유추 가능한 것은 생략 할 수 있으면 좋겠다.
이런거 없나? 
observable䯽 
어떤 쓰레드에서 수행하고,䯽 
필요한 데이터만 걸러내고,䯽 
데이터를 어떻게 변환하고,䯽 
오류 발생시에는 어떻게 대응할지,䯽 
어떤 쓰레드에서 결과를 받을지,䯽 
시작하면,䯽 
! 
필요한 경우 취소 할 수 있어야 한다.䯽 
! 
테스트도 쉬워야겠고!䯽 
유추 가능한 것은 생략 할 수 있으면 좋겠다.
이런거 없나? 
observable䯽 
.subscribeOn(background)䯽 
필요한 데이터만 걸러내고,䯽 
데이터를 어떻게 변환하고,䯽 
오류 발생시에는 어떻게 대응할지,䯽 
어떤 쓰레드에서 결과를 받을지,䯽 
시작하면,䯽 
! 
필요한 경우 취소 할 수 있어야 한다.䯽 
! 
테스트도 쉬워야겠고!䯽 
유추 가능한 것은 생략 할 수 있으면 좋겠다.
이런거 없나? 
observable䯽 
.subscribeOn(background)䯽 
.filter(paidUser())䯽 
데이터를 어떻게 변환하고,䯽 
오류 발생시에는 어떻게 대응할지,䯽 
어떤 쓰레드에서 결과를 받을지,䯽 
시작하면,䯽 
! 
필요한 경우 취소 할 수 있어야 한다.䯽 
! 
테스트도 쉬워야겠고!䯽 
유추 가능한 것은 생략 할 수 있으면 좋겠다.
이런거 없나? 
observable䯽 
.subscribeOn(background)䯽 
.filter(paidUser())䯽 
.map(stringToJson())䯽 
오류 발생시에는 어떻게 대응할지,䯽 
어떤 쓰레드에서 결과를 받을지,䯽 
시작하면,䯽 
! 
필요한 경우 취소 할 수 있어야 한다.䯽 
! 
테스트도 쉬워야겠고!䯽 
유추 가능한 것은 생략 할 수 있으면 좋겠다.
이런거 없나? 
observable䯽 
.subscribeOn(background)䯽 
.filter(paidUser())䯽 
.map(stringToJson())䯽 
.doOnError(handleError())䯽 
어떤 쓰레드에서 결과를 받을지,䯽 
시작하면,䯽 
! 
필요한 경우 취소 할 수 있어야 한다.䯽 
! 
테스트도 쉬워야겠고!䯽 
유추 가능한 것은 생략 할 수 있으면 좋겠다.
이런거 없나? 
observable䯽 
.subscribeOn(background)䯽 
.filter(paidUser())䯽 
.map(stringToJson())䯽 
.doOnError(handleError())䯽 
.observeOn(mainThread)䯽 
시작하면,䯽 
! 
필요한 경우 취소 할 수 있어야 한다.䯽 
! 
테스트도 쉬워야겠고!䯽 
유추 가능한 것은 생략 할 수 있으면 좋겠다.
이런거 없나? 
observable䯽 
.subscribeOn(background)䯽 
.filter(paidUser())䯽 
.map(stringToJson())䯽 
.doOnError(handleError())䯽 
.observeOn(mainThread)䯽 
.subscribe() -> subscription䯽 
! 
필요한 경우 취소 할 수 있어야 한다.䯽 
! 
테스트도 쉬워야겠고!䯽 
유추 가능한 것은 생략 할 수 있으면 좋겠다.
이런거 없나? 
observable䯽 
.subscribeOn(background)䯽 
.filter(paidUser())䯽 
.map(stringToJson())䯽 
.doOnError(handleError())䯽 
.observeOn(mainThread)䯽 
.subscribe() -> subscription䯽 
! 
subscription.unsubscribe()䯽 
! 
테스트도 쉬워야겠고!䯽 
유추 가능한 것은 생략 할 수 있으면 좋겠다.
이런거 없나? 
observable䯽 
.subscribeOn(background)䯽 
.filter(paidUser())䯽 
.map(stringToJson())䯽 
.doOnError(handleError())䯽 
.observeOn(mainThread)䯽 
.subscribe() -> subscription䯽 
! 
subscription.unsubscribe()䯽 
! 
! 
assert…(paidUser())䯽 
assert…(stringToJson())䯽 
assert…(handleError()) 
! 
유추 가능한 것은 생략 할 수 있으면 좋겠다.
이런거 없나? 
observable䯽 
.subscribeOn(background)䯽 
.filter(paidUser())䯽 
.map(stringToJson())䯽 
.doOnError(handleError())䯽 
.observeOn(mainThread)䯽 
.subscribe() -> subscription䯽 
! 
subscription.unsubscribe()䯽 
! 
!
RxJava
RxJava 
로직에만 집중 
테스트 용이성 
가독성 
이름짓기? 
내가 작성하는 코드가 어떤 쓰레드에서 돌아갈지 
지금 당장은 관심이 없어. 
왜냐하면, 실제 사용 할 시점에서 지정하면 되니까. 
모듈화가 쉽다 == 테스트하기 쉽다 
메소드 체이닝, 왼쪽에서 오른쪽으로 읽자 
코드가 하는 일은 코드 자체가 표현하도록 하자.
Custom Events 
3초 동안 입력이 없으면 추천 검색어를 제시
Custom Events 
D 
3초 동안 입력이 없으면 추천 검색어를 제시
Custom Events 
D E V 
3초 동안 입력이 없으면 추천 검색어를 제시
Custom Events 
1s 
D E V 
3초 동안 입력이 없으면 추천 검색어를 제시
Custom Events 
1s 2s 
D E V 
3초 동안 입력이 없으면 추천 검색어를 제시
Custom Events 
1s 2s 3s 
D E V 
dev 검색 요청 
3초 동안 입력이 없으면 추천 검색어를 제시
Custom Events 
1s 2s 3s 
D E V 
dev 검색 요청 
3초 동안 입력이 없으면 추천 검색어를 제시
Custom Events 
Custom Events 
lastInputTime 0 0 0 3 
D E V 
1s 2s 3s 
Thread 
Callback 
1. 쓰레드 만들고 
2. 이벤트 발생 시간 기록 
3. 마지막 이벤트와 현재 시간 비교 
4. 설정 값 이상의 차이가 발생시 콜백 
또는, 
1. 수행할 태스크를 작성 
2. 태스크 등록(postDelayed 사용) 
3. 이벤트 발생시 등록 이벤트 취소 
4. 등록 된 태스크가 수행되며 콜백
람다 
안드로이드 스튜디오 사용시 코드 폴딩을 통해 간결하게 표현되는 놈?
람다 
Runnable task = new Runnable(){ 
@Override 
public void run(){ 
System.out.println("Hello Lamba"); 
} 
}; 
Runnable task2 = () -> { System.out.println("Hello Lamba"); };
람다 
인터페이스가 하나의 메소드를 호출하면 
굳이 메소드의 이름을 적을 필요는 없으니 생략 
Runnable task = new Runnable(){ 
@Override 
public void run(){ 
System.out.println("Hello Lamba"); 
} 
}; 
Runnable task2 = () -> { System.out.println("Hello Lamba"); };
람다 
파라미터는 비었으니 빈 괄호를 넣어주자 
Runnable task = new Runnable(){ 
@Override 
public void run(){ 
System.out.println("Hello Lamba"); 
} 
}; 
Runnable task2 = () -> { System.out.println("Hello Lamba"); };
람다 
Runnable task = new Runnable(){ 
@Override 
public void run(){ 
System.out.println("Hello Lamba"); 
} 
}; 
Runnable task2 = () -> { System.out.println("Hello Lamba"); }; 
화살표 나오면 람다식! 
블럭 내의 내용은 그대로~
이클립스에서 람다 사용 
Xtend 
Xtend -> 자바 클래스로 변환 
• 안드로이드의 Swift 
Eclipse에서 만들었음에도 리팩토링 기능이 취약함. 
프로젝트가 커질수록 컴파일 타임이 급격히 증가 
자체적으로 Guava 활용. 테스트 작성시 코드를 
• 람다식은 익명 클래스를 통해 구현함 
IntelliJ에서는 그냥 텍스트파일 
빌드 프로세스를 고민 할 필요가 있음. 
극히 간결하게 유지 할 수 있음. 
메소드 단위 테스트가 불편 
• 자바코드로 컴파일 되므로 호환성 문제가 없음 
• 함수형 프로그래밍의 특징을 상당부분 수용함 
• Eclipse IDE 지원 
단점: 
호환성 끝판왕 
자바와 스칼라의 중간 어디쯤
안드로이드 스튜디오에서 람다 사용 
RetroLambda 
스튜디오의 기본기능인 폴딩도 괜찮지만, 
람다 사용이 조금 더 편함 
바이트 코드 조작을 통한 람다 사용 
• 암묵적 참조로 클래스 참조로 인한 메모리 문제가 없음
함수형 프로그래밍 
외부에서 건드릴 수 없음! 
람다식이 함수형 프로그래밍은 절대 아님!
함수형 프로그래밍의 특징 
불 대수 
x, y z 는 숫자이거나 집합 
(x ∧ z) ∨ (y ∧ z) = (x ∨ y) ∧ z
함수형 프로그래밍의 특징 
불 대수 
(x ∧ z) ∨ (y ∧ z) = (x ∨ y) ∧ z 
람다 대수 
클래스가 함수라면! 람다 대수에 의해 연산 가능! 
(λx.(λx.x)) y # λx.y
Circle Progress
RxJava 
Callback => Observable 
onDraw(Canvas canvas) 
Observer<Canvas>
RxJava 
Callback => Observable 
Subscriber<? super Canvas> canvasSubscriber; 
! 
@Override protected void onDraw(Canvas canvas) { 
super.onDraw(canvas); 
canvasSubscriber.onNext(canvas); 
} 
RxJava를 통해 콜백을 마치 컬렉션 처럼 바꿔줌
RxJava 
Callback => Observable 
60fps 
Observable 
onDraw(Canvas canvas) 
Observer<Canvas> 
이제 collection 처럼 사용가능
RxJava 
Callback => Observable 
Observer<Canvas> Observable 
함수형 특징을 가진 언어는 다들 비슷비슷 
Java 8’s Stream RxJava’s Observable 
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) )
RxJava 
Callback => Observable 
sineValueObservable 
drawCircle() 
Zip 
canvasObservable 
지퍼 맞음
RxJava 
Callback => Observable 
sineValueObservable 
drawCircle() 
Zip 
canvasObservable 
지퍼 맞음
RxJava 
Callback => Observable 
sineValueObservable 
drawCircle() 
Zip 
canvasObservable 
지퍼 맞음
RxJava 
Callback => Observable 
canvasObservable 
sineValueObservable 
drawCircle() 
Zip 
두 collection(obsavable)의 
각각 요소를 하나씩 결합! 
짝이 성사되면 그리기 수행!
RxJava 
Callback => Observable 
canvasObservable 
sineValueObservable 
drawCircle() 
Zip 
결과물 역시 Obserable 
이므로, 추가적인 연산이 
얼만든지 가능함~
왜 RxJava?
왜 RxJava?
Reactive Extension
ReactiveX 
RxJs의 형제
너무 어려워요… 
함수형 프로그래밍은 어려운게 아닙니다.䯽 
! 
익숙해지는데 시간이 좀 걸릴 뿐입니다.䯽 
! 
Rx와 함수형이 만능은 아닙니다.䯽 
! 
칼퇴근을 보장하진 못하지만,䯽 
! 
품질은 높아지고, 스트레스는 낮아집니다.䯽 
! 
어렵게 느껴지면, 금요일 라 스칼라 코딩단에 구경오세요䯽 
! 
같이 고민해봐요.䯽 
! 
…안드로이드 개발자 항시 대기 䯽 
!
RxJAVA?!
RxJava 
1. RxJava란?䯽 
! 
2. RxJava(Thread, 이벤트 합성, 시간 관리, Subject, 예외 관리)䯽 
! 
3. RxJava With MVVM䯽 
!
RxJava란? 
Excel䯽 
- 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.䯽 
! 
! 
A 
B 
C 
1 2 
10 20 
30 = A1+A2
RxJava란? 
Excel䯽 
- 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.䯽 
! 
! 
A 
B 
C 
1 2 
10 
30 = A1+A2
RxJava란? 
Excel䯽 
- 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.䯽 
! 
! 
A 
B 
C 
1 2 
10 
30 = A1+A2 
30
RxJava란? 
Excel䯽 
- 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.䯽 
! 
! 
A 
B 
C 
1 2 
10 
= A1+A2 
30
RxJava란? 
Excel䯽 
- 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.䯽 
! 
! 
A 
B 
C 
1 2 
10 
= A1+A2 
30 
40
RxJava - Observable, Observer란? 
Observable - 관측 가능한 값의 흐름를 나타내는 객체 (생산자)䯽 
Observer - 값의 흐름를 받는 객체 (소비자)䯽 
! 
Observable Observer 
Button 
Click String 
Network 
Byte[] 
Keyboard 
Text View 
Alert 
Image View 
Input Text 
Error 
Image 
String 
Visibility 
Image 
Event
RxJava - Observable, Observer란? 
Observable - 관측 가능한 값의 흐름를 나타내는 객체 (생산자)䯽 
- subscribe 함수를 통해 구독이 가능하며, 구독자에게 값을 흐름을 알려준다.䯽 
! 
Observer - 값의 흐름를 받는 객체 (소비자)䯽 
- Observable의 값의 흐름에 따라 onNext, onError, onCompelete를 호출 받는다.䯽 
! 
OnNext OnComplete 
OnError
RxJava - Observable, Observer란? 
eventSource.subscribe((event)-> { 
// some action. 
} 
); 
Observable 
Observer
RxJava - subscribe/unsubscribe 
subscribe / unsubcribe䯽 
- subscribe 를 통하여 Observable의 값의 변화를 구독하고,䯽 
unsubscribe를 통해 구독을 해지한다.䯽 
! 
! 
Button Function View 
Observable! 
(Operation! 
or! 
Producer) 
Observable! 
(Operation) 
Observer
RxJava - subscribe/unsubscribe 
subscribe / unsubcribe䯽 
- subscribe 를 통하여 Observable의 값의 변화를 구독하고,䯽 
unsubscribe를 통해 구독을 해지한다.䯽 
! 
! 
Button onSubscribe() Function subscribe() View 
Observable! 
(Operation! 
or! 
Producer) 
Observable! 
(Operation) 
Observer
RxJava - subscribe/unsubscribe 
subscribe / unsubcribe䯽 
- subscribe 를 통하여 Observable의 값의 변화를 구독하고,䯽 
unsubscribe를 통해 구독을 해지한다.䯽 
! 
! 
Button Function View 
Observable! 
(Operation! 
or! 
Producer) 
Observable! 
(Operation) 
Observer 
onSubscribe() subscribe() 
onNext() onNext()
RxJava - subscribe/unsubscribe 
subscribe / unsubcribe䯽 
- subscribe 를 통하여 Observable의 값의 변화를 구독하고,䯽 
unsubscribe를 통해 구독을 해지한다.䯽 
! 
! 
Button Function View 
Observable! 
(Operation! 
or! 
Producer) 
Observable! 
(Operation) 
Observer 
onSubscribe() subscribe() 
onNext() onNext() 
. 
. 
. 
. 
. 
.
RxJava - subscribe/unsubscribe 
subscribe / unsubcribe䯽 
- subscribe 를 통하여 Observable의 값의 변화를 구독하고,䯽 
unsubscribe를 통해 구독을 해지한다.䯽 
! 
! 
Button Function View 
Observable! 
(Operation! 
or! 
Producer) 
Observable! 
(Operation) 
Observer 
onSubscribe() subscribe() 
onNext() onNext() 
. 
. 
. 
. 
. 
. 
onNext() onNext()
RxJava - subscribe/unsubscribe 
subscribe / unsubcribe䯽 
- subscribe 를 통하여 Observable의 값의 변화를 구독하고,䯽 
unsubscribe를 통해 구독을 해지한다.䯽 
! 
! 
Button Function View 
Observable! 
(Operation! 
or! 
Producer) 
Observable! 
(Operation) 
Observer 
onSubscribe() subscribe() 
onNext() onNext() 
. 
. 
. 
. 
. 
. 
onNext() onNext() 
onComplete() onComplete()
RxJava - subscribe/unsubscribe 
subscribe / unsubcribe䯽 
- subscribe 를 통하여 Observable의 값의 변화를 구독하고,䯽 
unsubscribe를 통해 구독을 해지한다.䯽 
! 
! 
Button Function View 
Observable! 
(Operation! 
or! 
Producer) 
Observable! 
(Operation) 
Observer 
onSubscribe() subscribe() 
onNext() onNext() 
. 
. 
. 
. 
. 
. 
onNext() onNext() 
onComplete() onComplete() 
unsubscribe() unsubscribe()
RxJava - map 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 TextView에 출력하는 시나리오 
EditText 
Function 
TextView
RxJava - map 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 TextView에 출력하는 시나리오 
EditText 
Function 
TextView 
Text A 
fun(x) 
TextA-1
RxJava - map 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 TextView에 출력하는 시나리오 
EditText 
Function 
TextView 
Text B 
fun(x) 
TextB-1 
Text A 
fun(x) 
TextA-1
RxJava - map 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 TextView에 출력하는 시나리오 
EditText 
Function 
TextView 
Text B 
fun(x) 
TextB-1 
Text C 
fun(x) 
TextC-1 
Text A 
fun(x) 
TextA-1
RxJava - map 
map䯽 
- 전달되는 값에 함수를 적용해서 새로운 값을 만들어냄 䯽 
! 
! 
eventSource.map((value) -> {return fun(value);}) 
.subscribe((result) -> { 
! 
// show result. 
});
RxJava - flatMap 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 
EditText 
Async Function 
TextView
RxJava - flatMap 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 
EditText 
Async Function 
TextView 
Text A
RxJava - flatMap 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 
EditText 
Async Function 
TextView 
Text A 
fun(x)
RxJava - flatMap 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 
EditText 
Async Function 
TextView 
fun(x) 
TextA-1 
Text A
RxJava - flatMap 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 
EditText 
Async Function 
TextView 
Text A Text B 
fun(x) 
TextA-1
RxJava - flatMap 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 
EditText 
Async Function 
TextView 
fun(x) 
Text B 
TextA-1 
Text A 
fun(x)
RxJava - flatMap 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 
EditText 
Async Function 
TextView 
fun(x) 
TextA-1 
Text A 
fun(x) 
TextB-1 
Text B
RxJava - flatMap 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 
EditText 
Async Function 
TextView 
fun(x) 
Text B Text C 
TextA-1 
Text A 
fun(x) 
TextB-1
RxJava - flatMap 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 
EditText 
Async Function 
TextView 
fun(x) 
TextA-1 
Text A 
fun(x) 
Text C 
TextB-1 
Text B 
fun(x)
RxJava - flatMap 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 
EditText 
Async Function 
TextView 
fun(x) 
TextA-1 
Text A 
fun(x) 
TextB-1 
Text B 
fun(x) 
TextC-1 
Text C
RxJava - flatMap 
flatmap䯽 
- 미래에 0개 ~ n개의 결과를 반환하는 함수를 적용한다.䯽 
! 
! 
eventSource.flatMap((value) -> {return longlongFunc(value);}) 
.subscribe((Result) -> { 
! 
// show result. 
! 
}); 
Observable
Thread 관리
RxJava - Scheduler 
이미지 다운로드 시나리오䯽 
- 버튼을 클릭하면 이미지를 다운받아 표시하는 예제 
UI Thread 
IO Thread 
UI Thread 
Click 
Image 
Image
RxJava - Scheduler 
subscribeOn - 비동기 결과값을 가져오는 쓰레드를 결정한다 䯽 
observeOn - 결과 값을 처리할 쓰레드를 결정한다. 
ClickEvents.flatMap((event) -> { 
return asyncDownloadImage(params) 
.subscribeOn(Schedulers.io()); 
}) 
.observeOn(AndroidSchedulers.mainThread()) 
.subscribe((image) -> { 
// show result. 
});
RxJava - Scheduler 
observeOn䯽 
- 결과 값을 처리할 쓰레드를 결정한다. 
Event 
observeOn(MainThreadScheduler) 
Thread 
Main Thread
RxJava - Scheduler 
subscribeOn䯽 
- 비동기 결과값을 가져오는 쓰레드를 결정한다. 
subscribeOn(IOThreadScheduler) 
IO Thread 
Event 
IO Thread
RxJava - Scheduler 
Schedulers.computation()䯽 
- 단순 연산을 처리하는 Thread들의 Pool로 구성된 Scheduler.䯽 
! 
Schedulers.io()䯽 
- IO처리를 담당하는 Thread들의 Pool로 구성된 Scheduler.䯽 
- 필요에 따라 자동으로 Pool의 크기를 늘리거나 줄인다.䯽 
! 
Schedulers.newThread()䯽 
- 새로운 쓰레드를 만드는 Scheduler.䯽
RxJava - Scheduler 
AndroidSchedulers.mainThread( )䯽 
- Android의 Main Thread에서 작업을 수행한다.䯽 
! 
AndroidSchedulers.handlerThread(Handler handler)䯽 
- 특정 Thread를 사용하는 Handler이용하는 Scheduler를 생성한다.䯽 
! 
Schedulers.from(Executor executor)䯽 
- 특정 Executor를 사용하는 Scheduler를 생성한다.䯽 
! 
!
이벤트 합성
RxJava - combineLatest, merge 
combineLatest䯽 
- Observable 들의 이벤트들 중 가장 최신 이벤트 값을 합성해서 사용한다.䯽 
! 
Observable.combineLatest(color, shape, new Func2<Color, Shape, Image>() 
{ 
@Override 
public Image call(Color color, Shape shape) { 
return image.createFrom(color, shape); 
} 
} 
);
RxJava - combineLatest, merge 
combineLatest䯽 
- Observable 들의 중 가장 최신의 이벤트 값을 합성한다.䯽 
! 
Color combineLatest( ) 
Shape 
Image
RxJava - combineLatest, merge 
combineLatest䯽 
- Observable 들의 중 가장 최신의 이벤트 값을 합성한다.䯽 
! 
Color combineLatest( ) 
1 
Shape 
Image
RxJava - combineLatest, merge 
combineLatest䯽 
- Observable 들의 중 가장 최신의 이벤트 값을 합성한다.䯽 
! 
Color combineLatest( ) 
1 
Shape 
Image 
2 
2
RxJava - combineLatest, merge 
combineLatest䯽 
- Observable 들의 중 가장 최신의 이벤트 값을 합성한다.䯽 
! 
Color combineLatest( ) 
1 
Shape 
Image 
2 
2 
3 
3
RxJava - combineLatest, merge 
combineLatest䯽 
- Observable 들의 중 가장 최신의 이벤트 값을 합성한다.䯽 
! 
Color combineLatest( ) 
1 
Shape 
Image 
2 
2 
3 
4 
3 4
RxJava - combineLatest, merge 
merge䯽 
- Observable 들의 이벤트들을 합성해서 사용한다.䯽 
! 
Observable<Void> clickEvnets = 
Observable.merge(clickEventFromButtonA, 
clickEventFromButtonB);
RxJava - combineLatest, merge 
merge䯽 
- Observable 들의 이벤트들을 합성해서 사용한다.䯽 
! 
Login Button merge( ) 
Enter Key 
Login Event
RxJava - combineLatest, merge 
merge䯽 
- Observable 들의 이벤트들을 합성해서 사용한다.䯽 
! 
Login Button merge( ) 
Login Event 
1 
1 
Enter Key
RxJava - combineLatest, merge 
merge䯽 
- Observable 들의 이벤트들을 합성해서 사용한다.䯽 
! 
Login Button merge( ) 
Login Event 
1 
1 
Enter Key 
2 
2
RxJava - combineLatest, merge 
merge䯽 
- Observable 들의 이벤트들을 합성해서 사용한다.䯽 
! 
Login Button merge( ) 
Login Event 
1 
1 
Enter Key 
3 
2 
2 3
RxJava - combineLatest, merge 
merge䯽 
- Observable 들의 이벤트들을 합성해서 사용한다.䯽 
! 
Login Button merge( ) 
Login Event 
1 
1 
Enter Key 
3 
2 4 
2 3 
4
시간 관리
RxJava - Time 
예제) throttleWithTimeout䯽 
- 자동 완성 기능䯽 
! 
// 기본 변수 설정 
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));
RxJava - Time 
delay䯽 
- 모든 이벤트를 주어진 시간만큼 지연한다.䯽 
! 
Observer 
delay( )
RxJava - Time 
delay䯽 
- 모든 이벤트를 주어진 시간만큼 지연한다.䯽 
! 
1 
Observer 
delay( )
RxJava - Time 
delay䯽 
- 모든 이벤트를 주어진 시간만큼 지연한다.䯽 
! 
1 
Observer 
1 
delay( )
RxJava - Time 
delay䯽 
- 모든 이벤트를 주어진 시간만큼 지연한다.䯽 
! 
1 2 
Observer 
1 
delay( )
RxJava - Time 
delay䯽 
- 모든 이벤트를 주어진 시간만큼 지연한다.䯽 
! 
1 2 
Observer 
1 2 
delay( )
RxJava - Time 
delay䯽 
- 모든 이벤트를 주어진 시간만큼 지연한다.䯽 
! 
1 2 3 
Observer 
1 2 
delay( )
RxJava - Time 
delay䯽 
- 모든 이벤트를 주어진 시간만큼 지연한다.䯽 
! 
1 2 3 
Observer 
1 2 3 
delay( )
RxJava - Time 
throttleFirst䯽 
- 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 
! 
Observer 
throttleFirst( )
RxJava - Time 
throttleFirst䯽 
- 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 
! 
Observer 
throttleFirst( ) 
1 
1
RxJava - Time 
throttleFirst䯽 
- 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 
! 
Observer 
throttleFirst( ) 
1 
1
RxJava - Time 
throttleFirst䯽 
- 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 
! 
Observer 
throttleFirst( ) 
1 2 
1
RxJava - Time 
throttleFirst䯽 
- 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 
! 
Observer 
throttleFirst( ) 
1 
1 
2 3 
3
RxJava - Time 
throttleFirst䯽 
- 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 
! 
Observer 
throttleFirst( ) 
1 
1 
2 3 
3
RxJava - Time 
throttleFirst䯽 
- 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 
! 
Observer 
throttleFirst( ) 
1 
1 
2 3 4 
3
RxJava - Time 
throttleFirst䯽 
- 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 
! 
Observer 
3 5 
throttleFirst( ) 
1 
1 
3 
5 
2 4
RxJava - Time 
throttleFirst䯽 
- 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 
! 
Observer 
3 5 
throttleFirst( ) 
1 
1 
3 
5 
2 4
RxJava - Time 
throttleWithTimeout䯽 
- 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 
! 
Observer 
throttleWithTimeout( )
RxJava - Time 
throttleWithTimeout䯽 
- 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 
! 
Observer 
throttleWithTimeout( ) 
1
RxJava - Time 
throttleWithTimeout䯽 
- 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 
! 
Observer 
throttleWithTimeout( ) 
1
RxJava - Time 
throttleWithTimeout䯽 
- 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 
! 
Observer 
throttleWithTimeout( ) 
1 
1
RxJava - Time 
throttleWithTimeout䯽 
- 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 
! 
Observer 
throttleWithTimeout( ) 
1 2 
1
RxJava - Time 
throttleWithTimeout䯽 
- 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 
! 
Observer 
throttleWithTimeout( ) 
1 2 
1
RxJava - Time 
throttleWithTimeout䯽 
- 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 
! 
Observer 
1 2 3 
throttleWithTimeout( ) 
1
RxJava - Time 
throttleWithTimeout䯽 
- 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 
! 
Observer 
1 2 3 
throttleWithTimeout( ) 
1
RxJava - Time 
throttleWithTimeout䯽 
- 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 
! 
Observer 
1 2 3 4 
throttleWithTimeout( ) 
1
RxJava - Time 
throttleWithTimeout䯽 
- 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 
! 
Observer 
1 2 3 4 
throttleWithTimeout( ) 
1
RxJava - Time 
throttleWithTimeout䯽 
- 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 
! 
Observer 
1 2 3 4 
1 4 
throttleWithTimeout( )
Subject
RxJava - Subject(Observable + Observer) 
BehaviorSubject를 사용한 SharedPreferences 예제䯽 
! 
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));
RxJava - Subject(Observable + Observer) 
BehaviorSubject䯽 
! 
! 
! 
BehaviorSubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
BehaviorSubject䯽 
! 
! 
1 
! 
BehaviorSubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
BehaviorSubject䯽 
! 
! 
1 
! 
subscribe() 
BehaviorSubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
BehaviorSubject䯽 
! 
! 
1 
! 
subscribe() 
1 
BehaviorSubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
BehaviorSubject䯽 
! 
! 
! 
1 2 
2 
subscribe() 
1 
BehaviorSubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
BehaviorSubject䯽 
! 
! 
! 
1 2 
2 
subscribe() 
1 
subscribe() 
BehaviorSubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
BehaviorSubject䯽 
! 
! 
! 
1 2 
2 
subscribe() 
1 
2 
subscribe() 
BehaviorSubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
BehaviorSubject䯽 
! 
! 
! 
1 2 
2 
subscribe() 
1 
2 
3 
3 
3 
subscribe() 
BehaviorSubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
PublishSubject䯽 
! 
! 
PublishSubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
PublishSubject䯽 
! 
! 
1 
PublishSubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
PublishSubject䯽 
! 
! 
1 
subscribe() 
PublishSubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
PublishSubject䯽 
! 
! 
1 2 
2 
subscribe() 
PublishSubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
PublishSubject䯽 
! 
! 
1 2 
2 
subscribe() 
subscribe() 
PublishSubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
PublishSubject䯽 
! 
! 
1 2 
subscribe() 3 
2 
3 
3 
subscribe() 
PublishSubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
Replay Subject䯽 
! 
! 
ReplaySubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
Replay Subject䯽 
! 
! 
1 
ReplaySubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
Replay Subject䯽 
! 
! 
1 
subscribe() 
ReplaySubject 
Observer1 
Observer2
RxJava - Subject(Observable + Observer) 
Replay Subject䯽 
! 
! 
1 
subscribe() 
ReplaySubject 
Observer1 
Observer2 
1
RxJava - Subject(Observable + Observer) 
Replay Subject䯽 
! 
! 
1 2 
2 
subscribe() 
ReplaySubject 
Observer1 
Observer2 
1
RxJava - Subject(Observable + Observer) 
Replay Subject䯽 
! 
! 
1 2 
2 
subscribe() 
subscribe() 
ReplaySubject 
Observer1 
Observer2 
1
RxJava - Subject(Observable + Observer) 
Replay Subject䯽 
! 
! 
1 2 
2 
subscribe() 
subscribe() 
ReplaySubject 
Observer1 
Observer2 
1 
1
RxJava - Subject(Observable + Observer) 
Replay Subject䯽 
! 
! 
1 2 
2 
subscribe() 
subscribe() 
ReplaySubject 
Observer1 
Observer2 
1 
1 2
RxJava - Subject(Observable + Observer) 
Replay Subject䯽 
! 
! 
1 2 
2 
subscribe() 
subscribe() 
ReplaySubject 
Observer1 
Observer2 
1 
1 2 
3 
3 
3
예외 관리
RxJava - Error Handling 
doOnError䯽 
- 실패한 경우, 예외를 처리하는 기능을 수행할 수 있습니다.䯽 
! 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.observeOn(AndroidSchedulers.mainThread()) 
.doOnError((e) -> {showError(e);}) 
.subscribe((img) -> {showImage(img);}) 
1 
Observer 
1 X
RxJava - Error Handling 
doOnError䯽 
- 실패한 경우, 예외를 처리하는 기능을 수행할 수 있습니다.䯽 
! 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.observeOn(AndroidSchedulers.mainThread()) 
.doOnError((e) -> {showError(e);}) 
.subscribe((img) -> {showImage(img);}) 
1 
Observer 
1 X 
Error Handling
RxJava - Error Handling 
retry䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
! 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.retry() 
Observer 
retry()
RxJava - Error Handling 
retry䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
! 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.retry() 
Observer 
retry() 
1 
1
RxJava - Error Handling 
retry䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
! 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.retry() 
Observer 
retry() 
1 X 
1
RxJava - Error Handling 
retry䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
! 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.retry() 
Observer 
retry() 
1 X 
1
RxJava - Error Handling 
retry䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
! 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.retry() 
Observer 
retry() 
1 X 
1 
3 
3
RxJava - Error Handling 
retry(int n)䯽 
- 실패한 경우 자동으로 n회 재시도 합니다.䯽 
! 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.retry(1) 
Observer 
retry(1)
RxJava - Error Handling 
retry(int n)䯽 
- 실패한 경우 자동으로 n회 재시도 합니다.䯽 
! 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.retry(1) 
Observer 
retry(1) 
1 
1
RxJava - Error Handling 
retry(int n)䯽 
- 실패한 경우 자동으로 n회 재시도 합니다.䯽 
! 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.retry(1) 
Observer 
retry(1) 
1 X 
1
RxJava - Error Handling 
retry(int n)䯽 
- 실패한 경우 자동으로 n회 재시도 합니다.䯽 
! 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.retry(1) 
Observer 
retry(1) 
1 X 
1
RxJava - Error Handling 
retry(int n)䯽 
- 실패한 경우 자동으로 n회 재시도 합니다.䯽 
! 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.retry(1) 
Observer 
retry(1) 
1 X 
1 
2 
2
RxJava - Error Handling 
retry(int n)䯽 
- 실패한 경우 자동으로 n회 재시도 합니다.䯽 
! 
2 X 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.retry(1) 
Observer 
retry(1) 
1 X 
1 
2 
X
RxJava - Error Handling 
retryWhen(Observable)䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
! 
Observer 
retryWhen()
RxJava - Error Handling 
retryWhen(Observable)䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
! 
Observer 
retryWhen() 
1 
1
RxJava - Error Handling 
retryWhen(Observable)䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
! 
Observer 
retryWhen() 
1 X 
1
RxJava - Error Handling 
retryWhen(Observable)䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
! 
Observer 
retryWhen() 
1 X 
1 
delay(3, SECODS)
RxJava - Error Handling 
retryWhen(Observable)䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
! 
Observer 
retryWhen() 
1 X 
1 
delay(3, SECODS)
RxJava - Error Handling 
retryWhen(Observable)䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
! 
Observer 
retryWhen() 
1 X 
1 
3 
3 
delay(3, SECODS)
RxJava - Error Handling 
retryWhen(Observable)䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
! 
Observer 
retryWhen() 
! 
GetDataFromNetwork() 
1 X 
1 
3 
3 
.subscribeOn(Schedulers.io()) 
.retryWhen((observable) -> 
delay(3, SECODS) 
{ 
// 3초마다 재시도 
return observable.delay(3, TimeUnit.SECONDS); 
})
MVVM With RxJava
RxJava - MVVM 
Loading Indicator 예제䯽 
버튼을 클릭하면 다운로드가 완료될 때까지 Loading indicator를 표시한다.䯽 
! 
! 
// 버튼 클릭 이벤트 
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); 
)}
RxJava - MVVM 
Loading Indicator 예제䯽 
버튼을 클릭하면 다운로드가 완료될 때까지 Loading indicator를 표시한다.䯽 
! 
! 
// 버튼 클릭 이벤트 
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
RxJava - MVVM 
Model View 
User Info 
String String 
Login Info 
String 
Profile Image 
Text View 
Alert 
Image View 
Input Text 
Error 
Image 
Image 
Visibility 
Image 
Event 
View Model 
운영체제에䯽 
의존적 
운영체제에䯽 
독립적
RxJava - MVVM 
Model View 
User Info 
String String 
Login Info 
String 
Profile Image 
Text View 
Alert 
Image View 
Input Text 
Error 
Image 
Image 
Visibility 
Image 
Event 
View Model 
재사용이䯽 
어려움 
재사용이 
원활함
RxJava - MVVM 
Model View 
User Info 
String String 
Login Info 
String 
Profile Image 
Text View 
Alert 
Image View 
Input Text 
Error 
Image 
Image 
Visibility 
Image 
Event 
View Model 
테스트 불 
가능 코드 
테스트 가능 코드 
연결 코드
결론
왜 Reactive Programming 인가? 
프로그램의 일관성을 유지하는 통일된 방식이 필요䯽 
- Event, Thread, 시간, Exception을 처리하기에는 Callback은 조합이 어렵다.䯽 
- 그러므로 개개인이 각각의 방식으로 조합하여 복잡성이 증대된다.䯽 
! 
! 
단순 객체지향으로는 큰 프로그램을 만들기 어렵다.䯽 
- 객체지향은 내부의 상세한 구현을 숨긴다.䯽 
- 이로인해 잘 만들지 않으면 기대와 다른 동작들로 인해 복잡도가 증가한다.䯽 
- 이를 해결하기 위해 객체가 객체를 감싸고 또다시 감싸는 등의 문제가 발생한다.䯽 
! 
!
왜 Reactive Programming 인가? 
프로그램의 일관성을 유지하는 통일된 방식이 필요䯽 
- Event, Thread, 시간, Exception을 처리하기에는 Callback은 조합이 어렵다.䯽 
- 그러므로 개개인이 각각의 방식으로 조합하여 복잡성이 증대된다.䯽 
! 
! 
단순 객체지향으로는 큰 프로그램을 만들기 어렵다.䯽 
- 객체지향은 내부의 상세한 구현을 숨긴다.䯽 
- 이로인해 잘 만들지 않으면 기대와 다른 동작들로 인해 복잡도가 증가한다.䯽 
- 이를 해결하기 위해 객체가 객체를 감싸고 또다시 감싸는 등의 문제가 발생한다.䯽 
! 
! 
통일된 방식으로 Event, Thread, Time, Exception을 처리할 수 있는 방법 제공
왜 Reactive Programming 인가? 
프로그램의 일관성을 유지하는 통일된 방식이 필요䯽 
- Event, Thread, 시간, Exception을 처리하기에는 Callback은 조합이 어렵다.䯽 
- 그러므로 개개인이 각각의 방식으로 조합하여 복잡성이 증대된다.䯽 
! 
! 
단순 객체지향으로는 큰 프로그램을 만들기 어렵다.䯽 
- 객체지향은 내부의 상세한 구현을 숨긴다.䯽 
- 이로인해 잘 만들지 않으면 기대와 다른 동작들로 인해 복잡도가 증가한다.䯽 
- 이를 해결하기 위해 객체가 객체를 감싸고 또다시 감싸는 등의 문제가 발생한다.䯽 
! 
! 
통일된 방식으로 Event, Thread, Time, Exception을 처리할 수 있는 방법 제공 
외부에 제공할 수 있는 읽기 전용의 Observable을 제공하며 내용을 감추지 
않아도 됨
왜 Reactive Programming 인가? 
보다 테스트하기 쉬운 구조가 필요하다.䯽 
- 일반적인 구현에서는 가장 내부 깊은 곳에 View, Activity 등이 존재한다.䯽 
- 이로 인해 테스트에서 View를 제거하지 못해 테스트가 힘들어진다.䯽
왜 Reactive Programming 인가? 
보다 테스트하기 쉬운 구조가 필요하다.䯽 
- 일반적인 구현에서는 가장 내부 깊은 곳에 View, Activity 등이 존재한다.䯽 
- 이로 인해 테스트에서 View를 제거하지 못해 테스트가 힘들어진다.䯽 
MVVM의 구조를 활용하여 OS 종속적인 부분을 최대한 배제하고 테스트할 수 있음
감사합니다.

More Related Content

What's hot

헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리은숙 이
 
Startup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSStartup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSCirculus
 
Web Components 101 polymer & brick
Web Components 101 polymer & brickWeb Components 101 polymer & brick
Web Components 101 polymer & brickyongwoo Jeon
 
[NDC 2016] 유니티, iOS에서 LINQ 사용하기
[NDC 2016] 유니티, iOS에서 LINQ 사용하기[NDC 2016] 유니티, iOS에서 LINQ 사용하기
[NDC 2016] 유니티, iOS에서 LINQ 사용하기Daehee Kim
 
[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?NAVER D2
 
Html5 web workers
Html5 web workersHtml5 web workers
Html5 web workersWoo Jin Kim
 
windows via c++ Ch 5. Job
windows via c++ Ch 5. Jobwindows via c++ Ch 5. Job
windows via c++ Ch 5. JobHyosung Jeon
 
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개beom kyun choi
 
[115] clean fe development_윤지수
[115] clean fe development_윤지수[115] clean fe development_윤지수
[115] clean fe development_윤지수NAVER D2
 
NDC14 - Rx와 Functional Reactive Programming으로 고성능 서버 만들기
NDC14 - Rx와 Functional Reactive Programming으로 고성능 서버 만들기NDC14 - Rx와 Functional Reactive Programming으로 고성능 서버 만들기
NDC14 - Rx와 Functional Reactive Programming으로 고성능 서버 만들기Jong Wook Kim
 
Leadweb Nodejs
Leadweb NodejsLeadweb Nodejs
Leadweb Nodejs근호 최
 
Startup JavaScript 9 - Socket.IO 실시간 통신
Startup JavaScript 9 - Socket.IO 실시간 통신Startup JavaScript 9 - Socket.IO 실시간 통신
Startup JavaScript 9 - Socket.IO 실시간 통신Circulus
 
Jdk(java) 7 - 5. invoke-dynamic
Jdk(java) 7 - 5. invoke-dynamicJdk(java) 7 - 5. invoke-dynamic
Jdk(java) 7 - 5. invoke-dynamicknight1128
 
7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성HyeonSeok Choi
 
Javascript everywhere - Node.js | Devon 2012
Javascript everywhere - Node.js | Devon 2012Javascript everywhere - Node.js | Devon 2012
Javascript everywhere - Node.js | Devon 2012Daum DNA
 
Node.js 현재와 미래
Node.js 현재와 미래Node.js 현재와 미래
Node.js 현재와 미래JeongHun Byeon
 

What's hot (20)

헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리헷갈리는 자바스크립트 정리
헷갈리는 자바스크립트 정리
 
Startup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSStartup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JS
 
Web Components 101 polymer & brick
Web Components 101 polymer & brickWeb Components 101 polymer & brick
Web Components 101 polymer & brick
 
[NDC 2016] 유니티, iOS에서 LINQ 사용하기
[NDC 2016] 유니티, iOS에서 LINQ 사용하기[NDC 2016] 유니티, iOS에서 LINQ 사용하기
[NDC 2016] 유니티, iOS에서 LINQ 사용하기
 
[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?
 
Node.js intro
Node.js introNode.js intro
Node.js intro
 
Html5 web workers
Html5 web workersHtml5 web workers
Html5 web workers
 
windows via c++ Ch 5. Job
windows via c++ Ch 5. Jobwindows via c++ Ch 5. Job
windows via c++ Ch 5. Job
 
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
 
[115] clean fe development_윤지수
[115] clean fe development_윤지수[115] clean fe development_윤지수
[115] clean fe development_윤지수
 
NDC14 - Rx와 Functional Reactive Programming으로 고성능 서버 만들기
NDC14 - Rx와 Functional Reactive Programming으로 고성능 서버 만들기NDC14 - Rx와 Functional Reactive Programming으로 고성능 서버 만들기
NDC14 - Rx와 Functional Reactive Programming으로 고성능 서버 만들기
 
What is the meteor?
What is the meteor?What is the meteor?
What is the meteor?
 
Leadweb Nodejs
Leadweb NodejsLeadweb Nodejs
Leadweb Nodejs
 
Express 프레임워크
Express 프레임워크Express 프레임워크
Express 프레임워크
 
Startup JavaScript 9 - Socket.IO 실시간 통신
Startup JavaScript 9 - Socket.IO 실시간 통신Startup JavaScript 9 - Socket.IO 실시간 통신
Startup JavaScript 9 - Socket.IO 실시간 통신
 
Jdk(java) 7 - 5. invoke-dynamic
Jdk(java) 7 - 5. invoke-dynamicJdk(java) 7 - 5. invoke-dynamic
Jdk(java) 7 - 5. invoke-dynamic
 
7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성
 
Javascript everywhere - Node.js | Devon 2012
Javascript everywhere - Node.js | Devon 2012Javascript everywhere - Node.js | Devon 2012
Javascript everywhere - Node.js | Devon 2012
 
Spring Boot 1
Spring Boot 1Spring Boot 1
Spring Boot 1
 
Node.js 현재와 미래
Node.js 현재와 미래Node.js 현재와 미래
Node.js 현재와 미래
 

Viewers also liked

Functional Reactive Programming with RxJS
Functional Reactive Programming with RxJSFunctional Reactive Programming with RxJS
Functional Reactive Programming with RxJSstefanmayer13
 
Functional Reactive Programming With RxSwift
Functional Reactive Programming With RxSwiftFunctional Reactive Programming With RxSwift
Functional Reactive Programming With RxSwift선협 이
 
Cascadia.js: Don't Cross the Streams
Cascadia.js: Don't Cross the StreamsCascadia.js: Don't Cross the Streams
Cascadia.js: Don't Cross the Streamsmattpodwysocki
 
RxJS and Reactive Programming - Modern Web UI - May 2015
RxJS and Reactive Programming - Modern Web UI - May 2015RxJS and Reactive Programming - Modern Web UI - May 2015
RxJS and Reactive Programming - Modern Web UI - May 2015Ben Lesh
 
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015NAVER / MusicPlatform
 
혁신적인 웹컴포넌트 라이브러리 - Polymer
혁신적인 웹컴포넌트 라이브러리 - Polymer혁신적인 웹컴포넌트 라이브러리 - Polymer
혁신적인 웹컴포넌트 라이브러리 - PolymerJae Sung Park
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
Module, AMD, RequireJS
Module, AMD, RequireJSModule, AMD, RequireJS
Module, AMD, RequireJS偉格 高
 
System webpack-jspm
System webpack-jspmSystem webpack-jspm
System webpack-jspmJesse Warden
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJSKyung Yeol Kim
 
React in Native Apps - Meetup React - 20150409
React in Native Apps - Meetup React - 20150409React in Native Apps - Meetup React - 20150409
React in Native Apps - Meetup React - 20150409Minko3D
 
맛만 보자 액터 모델이란
맛만 보자 액터 모델이란 맛만 보자 액터 모델이란
맛만 보자 액터 모델이란 jbugkorea
 
React JS and why it's awesome
React JS and why it's awesomeReact JS and why it's awesome
React JS and why it's awesomeAndrew Hull
 
LetSwift RxSwift 시작하기
LetSwift RxSwift 시작하기LetSwift RxSwift 시작하기
LetSwift RxSwift 시작하기Wanbok Choi
 

Viewers also liked (15)

Functional Reactive Programming with RxJS
Functional Reactive Programming with RxJSFunctional Reactive Programming with RxJS
Functional Reactive Programming with RxJS
 
Functional Reactive Programming With RxSwift
Functional Reactive Programming With RxSwiftFunctional Reactive Programming With RxSwift
Functional Reactive Programming With RxSwift
 
Cascadia.js: Don't Cross the Streams
Cascadia.js: Don't Cross the StreamsCascadia.js: Don't Cross the Streams
Cascadia.js: Don't Cross the Streams
 
RxJS and Reactive Programming - Modern Web UI - May 2015
RxJS and Reactive Programming - Modern Web UI - May 2015RxJS and Reactive Programming - Modern Web UI - May 2015
RxJS and Reactive Programming - Modern Web UI - May 2015
 
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
 
혁신적인 웹컴포넌트 라이브러리 - Polymer
혁신적인 웹컴포넌트 라이브러리 - Polymer혁신적인 웹컴포넌트 라이브러리 - Polymer
혁신적인 웹컴포넌트 라이브러리 - Polymer
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
 
Module, AMD, RequireJS
Module, AMD, RequireJSModule, AMD, RequireJS
Module, AMD, RequireJS
 
System webpack-jspm
System webpack-jspmSystem webpack-jspm
System webpack-jspm
 
Angular2 ecosystem
Angular2 ecosystemAngular2 ecosystem
Angular2 ecosystem
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJS
 
React in Native Apps - Meetup React - 20150409
React in Native Apps - Meetup React - 20150409React in Native Apps - Meetup React - 20150409
React in Native Apps - Meetup React - 20150409
 
맛만 보자 액터 모델이란
맛만 보자 액터 모델이란 맛만 보자 액터 모델이란
맛만 보자 액터 모델이란
 
React JS and why it's awesome
React JS and why it's awesomeReact JS and why it's awesome
React JS and why it's awesome
 
LetSwift RxSwift 시작하기
LetSwift RxSwift 시작하기LetSwift RxSwift 시작하기
LetSwift RxSwift 시작하기
 

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

20201121 코드 삼분지계
20201121 코드 삼분지계20201121 코드 삼분지계
20201121 코드 삼분지계Chiwon Song
 
Java Virtual Machine, Call stack, Java Byte Code
Java Virtual Machine, Call stack, Java Byte CodeJava Virtual Machine, Call stack, Java Byte Code
Java Virtual Machine, Call stack, Java Byte CodeJavajigi Jaesung
 
HolubOnPatterns/chapter3_3
HolubOnPatterns/chapter3_3HolubOnPatterns/chapter3_3
HolubOnPatterns/chapter3_3suitzero
 
Domain Specific Languages With Groovy
Domain Specific Languages With GroovyDomain Specific Languages With Groovy
Domain Specific Languages With GroovyTommy C. Kang
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기현철 조
 
.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기Seong Won Mun
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)beom kyun choi
 
Design Pattern - Multithread Ch10
Design Pattern - Multithread Ch10Design Pattern - Multithread Ch10
Design Pattern - Multithread Ch10hyun soomyung
 
[드론] 펌웨어 분석 [2015.5.23]
[드론] 펌웨어 분석 [2015.5.23][드론] 펌웨어 분석 [2015.5.23]
[드론] 펌웨어 분석 [2015.5.23]chcbaram
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)문익 장
 
Clean Front-End Development
Clean Front-End DevelopmentClean Front-End Development
Clean Front-End Development지수 윤
 
EcmaScript6(2015) Overview
EcmaScript6(2015) OverviewEcmaScript6(2015) Overview
EcmaScript6(2015) Overviewyongwoo Jeon
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010Ryan Park
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10Ryan Park
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기jongho jeong
 
Ai C#세미나
Ai C#세미나Ai C#세미나
Ai C#세미나Astin Choi
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GDG Korea
 
Java jungsuk3 ch14_lambda_stream
Java jungsuk3 ch14_lambda_streamJava jungsuk3 ch14_lambda_stream
Java jungsuk3 ch14_lambda_stream성 남궁
 

Similar to [1B4]안드로이드 동시성_프로그래밍 (20)

20201121 코드 삼분지계
20201121 코드 삼분지계20201121 코드 삼분지계
20201121 코드 삼분지계
 
Java Virtual Machine, Call stack, Java Byte Code
Java Virtual Machine, Call stack, Java Byte CodeJava Virtual Machine, Call stack, Java Byte Code
Java Virtual Machine, Call stack, Java Byte Code
 
HolubOnPatterns/chapter3_3
HolubOnPatterns/chapter3_3HolubOnPatterns/chapter3_3
HolubOnPatterns/chapter3_3
 
Domain Specific Languages With Groovy
Domain Specific Languages With GroovyDomain Specific Languages With Groovy
Domain Specific Languages With Groovy
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
 
.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)
 
Design Pattern - Multithread Ch10
Design Pattern - Multithread Ch10Design Pattern - Multithread Ch10
Design Pattern - Multithread Ch10
 
[드론] 펌웨어 분석 [2015.5.23]
[드론] 펌웨어 분석 [2015.5.23][드론] 펌웨어 분석 [2015.5.23]
[드론] 펌웨어 분석 [2015.5.23]
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)
 
Clean Front-End Development
Clean Front-End DevelopmentClean Front-End Development
Clean Front-End Development
 
Spring Boot 2
Spring Boot 2Spring Boot 2
Spring Boot 2
 
miss_pattern_v2
miss_pattern_v2miss_pattern_v2
miss_pattern_v2
 
EcmaScript6(2015) Overview
EcmaScript6(2015) OverviewEcmaScript6(2015) Overview
EcmaScript6(2015) Overview
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기
 
Ai C#세미나
Ai C#세미나Ai C#세미나
Ai C#세미나
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
 
Java jungsuk3 ch14_lambda_stream
Java jungsuk3 ch14_lambda_streamJava jungsuk3 ch14_lambda_stream
Java jungsuk3 ch14_lambda_stream
 

More from NAVER D2

[211] 인공지능이 인공지능 챗봇을 만든다
[211] 인공지능이 인공지능 챗봇을 만든다[211] 인공지능이 인공지능 챗봇을 만든다
[211] 인공지능이 인공지능 챗봇을 만든다NAVER D2
 
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...NAVER D2
 
[215] Druid로 쉽고 빠르게 데이터 분석하기
[215] Druid로 쉽고 빠르게 데이터 분석하기[215] Druid로 쉽고 빠르게 데이터 분석하기
[215] Druid로 쉽고 빠르게 데이터 분석하기NAVER D2
 
[245]Papago Internals: 모델분석과 응용기술 개발
[245]Papago Internals: 모델분석과 응용기술 개발[245]Papago Internals: 모델분석과 응용기술 개발
[245]Papago Internals: 모델분석과 응용기술 개발NAVER D2
 
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈NAVER D2
 
[235]Wikipedia-scale Q&A
[235]Wikipedia-scale Q&A[235]Wikipedia-scale Q&A
[235]Wikipedia-scale Q&ANAVER D2
 
[244]로봇이 현실 세계에 대해 학습하도록 만들기
[244]로봇이 현실 세계에 대해 학습하도록 만들기[244]로봇이 현실 세계에 대해 학습하도록 만들기
[244]로봇이 현실 세계에 대해 학습하도록 만들기NAVER D2
 
[243] Deep Learning to help student’s Deep Learning
[243] Deep Learning to help student’s Deep Learning[243] Deep Learning to help student’s Deep Learning
[243] Deep Learning to help student’s Deep LearningNAVER D2
 
[234]Fast & Accurate Data Annotation Pipeline for AI applications
[234]Fast & Accurate Data Annotation Pipeline for AI applications[234]Fast & Accurate Data Annotation Pipeline for AI applications
[234]Fast & Accurate Data Annotation Pipeline for AI applicationsNAVER D2
 
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load BalancingOld version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load BalancingNAVER D2
 
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지NAVER D2
 
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기NAVER D2
 
[224]네이버 검색과 개인화
[224]네이버 검색과 개인화[224]네이버 검색과 개인화
[224]네이버 검색과 개인화NAVER D2
 
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)NAVER D2
 
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기NAVER D2
 
[213] Fashion Visual Search
[213] Fashion Visual Search[213] Fashion Visual Search
[213] Fashion Visual SearchNAVER D2
 
[232] TensorRT를 활용한 딥러닝 Inference 최적화
[232] TensorRT를 활용한 딥러닝 Inference 최적화[232] TensorRT를 활용한 딥러닝 Inference 최적화
[232] TensorRT를 활용한 딥러닝 Inference 최적화NAVER D2
 
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지NAVER D2
 
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터NAVER D2
 
[223]기계독해 QA: 검색인가, NLP인가?
[223]기계독해 QA: 검색인가, NLP인가?[223]기계독해 QA: 검색인가, NLP인가?
[223]기계독해 QA: 검색인가, NLP인가?NAVER D2
 

More from NAVER D2 (20)

[211] 인공지능이 인공지능 챗봇을 만든다
[211] 인공지능이 인공지능 챗봇을 만든다[211] 인공지능이 인공지능 챗봇을 만든다
[211] 인공지능이 인공지능 챗봇을 만든다
 
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
 
[215] Druid로 쉽고 빠르게 데이터 분석하기
[215] Druid로 쉽고 빠르게 데이터 분석하기[215] Druid로 쉽고 빠르게 데이터 분석하기
[215] Druid로 쉽고 빠르게 데이터 분석하기
 
[245]Papago Internals: 모델분석과 응용기술 개발
[245]Papago Internals: 모델분석과 응용기술 개발[245]Papago Internals: 모델분석과 응용기술 개발
[245]Papago Internals: 모델분석과 응용기술 개발
 
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
 
[235]Wikipedia-scale Q&A
[235]Wikipedia-scale Q&A[235]Wikipedia-scale Q&A
[235]Wikipedia-scale Q&A
 
[244]로봇이 현실 세계에 대해 학습하도록 만들기
[244]로봇이 현실 세계에 대해 학습하도록 만들기[244]로봇이 현실 세계에 대해 학습하도록 만들기
[244]로봇이 현실 세계에 대해 학습하도록 만들기
 
[243] Deep Learning to help student’s Deep Learning
[243] Deep Learning to help student’s Deep Learning[243] Deep Learning to help student’s Deep Learning
[243] Deep Learning to help student’s Deep Learning
 
[234]Fast & Accurate Data Annotation Pipeline for AI applications
[234]Fast & Accurate Data Annotation Pipeline for AI applications[234]Fast & Accurate Data Annotation Pipeline for AI applications
[234]Fast & Accurate Data Annotation Pipeline for AI applications
 
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load BalancingOld version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
 
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
 
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
 
[224]네이버 검색과 개인화
[224]네이버 검색과 개인화[224]네이버 검색과 개인화
[224]네이버 검색과 개인화
 
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
 
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
 
[213] Fashion Visual Search
[213] Fashion Visual Search[213] Fashion Visual Search
[213] Fashion Visual Search
 
[232] TensorRT를 활용한 딥러닝 Inference 최적화
[232] TensorRT를 활용한 딥러닝 Inference 최적화[232] TensorRT를 활용한 딥러닝 Inference 최적화
[232] TensorRT를 활용한 딥러닝 Inference 최적화
 
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
 
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
 
[223]기계독해 QA: 검색인가, NLP인가?
[223]기계독해 QA: 검색인가, NLP인가?[223]기계독해 QA: 검색인가, NLP인가?
[223]기계독해 QA: 검색인가, NLP인가?
 

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

  • 1. 안드로이드 동시성 프로그래밍 - RxJava를 활용한 Functional Reactive Programming 최정열 / Sivaworks / 라 스칼라 코딩단䯽 email: myeesan@gmail.com䯽 조현태 / Line + / 라 스칼라 코딩단䯽 email: waynejo1024@gmail.com
  • 3. 오늘의 목표 함수형 프로그래밍에 한 번 관심을 가져보시는 것은 어떨까요?䯽 ! 함수형을 프로그래밍을 익히는 것이 가장 큰 도전…䯽 ! 더 어려운 부분은 절차형과 함수형에서 효율적인 방법을 선택하는 것!䯽 ! 라 스칼라 코딩단: https://groups.google.com/forum/#!forum/scala-korea䯽 ! 샘플 저장소: https://github.com/orgs/FridayCoders/dashboard (업데이트 예정)䯽 !
  • 4. 안드로이드 동시성 프로그래밍 1. Plain Old Java Concurrent Programming䯽 2. 생명주기와 동시성 프로그래밍䯽 3. Sequencial Tasks & Parellel Tasks䯽 4. 람다 & 함수형 프로그래밍䯽
  • 6. Concurrent Programming Android Concurrent Programming Thread concurrent package Handler AsyncTask Service AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso AndroidUniversalImageLoader AndroidAsync(Http), ION AndroidAnnotations Guava greenrobot/EventBus otto
  • 7. Concurrent Programming Thread new Thread() { @Override public void run() { URL url = new URL(strUrl); HttpURLConnection urlConnection = ... urlConnection.connect(); iStream = urlConnection.getInputStream(); bitmap = BitmapFactory.decodeStream(iStream); } }.start(); Background
  • 8. 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
  • 9. 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
  • 10. Thread class 예외는 백그라운드에서 발생하지만, 메시지는 UI쓰레드로… 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
  • 11. 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){ // ... } ...
  • 12. 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) { ... } 보기 편하게 람다식으로…
  • 13. 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? ! 구현을 들여다 보지 않으면 모르겠는걸?
  • 14. Thread class 현재 쓰레드에서 메소드 호출과 UI쓰레드 호출을 비교 Bitmap downloadUrl(String strUrl) { ... handleException(e, ()-> “다운로드 실패” ); } ! ! ! // 1 void handleException(Exception e, OnError onError) { runOnUiThread(new Runnable(){ void run(){ log.d(onError.call());} } UI 쓰레드 로깅은 백그라운드에서 처리해도 되는데, UI 쓰레드에서 호출하는건 낭비 닐까? } ! // 2 void handleException(Exception e, OnError onError) { log.d(onError.call()); } 현재 쓰레드 (Background)
  • 15. 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(); } 뷰를 조작하는 코드를 전달 하면?
  • 16. Thread class CalledFromWrongThreadException 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 쓰레드 외에서는 뷰를 조작 할 수 없음!
  • 17. 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(); } 모든 메소드의 이름을 이렇게 짓는 것은 무리야!
  • 19. 생명주기와 쓰레드 쓰레드를 시작했으면 독립적으로 존재 UI Thread Activity A onDestroy() Background Thread Activity B Activity A가 종료 되어도 쓰레드는 독립적으로 살아 있음
  • 20. 생명주기와 쓰레드 Inner class 사용시 메무리 누수 UI Thread Activity A Reference Background Thread 쓰레드가 암묵적으로 참조하고 있어서, onDestroy()가 호출 된 후에도, GC되지 않음! Activity B onDestroy() 성능 저하, 메모리 낭비 Inner class로 쓰레드를 만들면 암북적으로 액티비티를 참조
  • 21. 생명주기와 쓰레드 쓰레드를 종료 시킬 깔끔한 방법의 필요성 onStop() onDestroy() UI Thread Activity A Background Thread 어디선간 쓰레드를 종료 해야겠네! 어떻게 종료 시키지? interrupt? 또, try ~ catch ~ final?
  • 22. 생명주기와 쓰레드 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 작업이 끝나면 콜백을 통해 결과를 전달~
  • 23. 생명주기와 쓰레드 예외 발생 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요소에는 직접 처리 할 수 없으므로 콜백 메소드를 추가.
  • 24. Concurrent Programming Android Concurrent Programming Thread concurrent package Handler AsyncTask Service AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso Executor + Thread pool + Future … Thread 보다 추상화된 제어가 가능! AndroidUniversalImageLoader AndroidAsync(Http), ION AndroidAnnotations Guava greenrobot/EventBus otto
  • 25. Concurrent Programming Android Concurrent Programming Thread concurrent package Handler AsyncTask Service 안드로이드의 UI Thread를 관리하는 놈. Looper와 함께 사용하고, Looper는 메시지 큐를 가지고 있어서 순차 실행을 보장! AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso AndroidUniversalImageLoader AndroidAsync(Http), ION AndroidAnnotations Guava greenrobot/EventBus otto
  • 26. Concurrent Programming Android Concurrent Programming Thread concurrent package Handler AsyncTask Service AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso AndroidUniversalImageLoader AndroidAsync(Http), ION Handler + 탬플릿 메소드 패턴 AndroidAnnotations Guava greenrobot/EventBus otto
  • 27. AsyncTask class 다운로드 + Ui + 예외 처리 (?) @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 쓰레드
  • 28. AsyncTask class 다운로드 + Ui + 예외 처리 (?) @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); } 백그라운드 쓰레드
  • 29. AsyncTask class 다운로드 + Ui + 예외 처리 (?) @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로 어떻 게 전달하지?
  • 30. Concurrent Programming Android Concurrent Programming Thread concurrent package Handler AsyncTask Service AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso AndroidUniversalImageLoader AndroidAsync(Http), ION AndroidAnnotations Guava greenrobot/EventBus otto 액티비티의 생명 주기로 부터 영향을 받지 않음!
  • 31. Concurrent Programming Android Concurrent Programming Thread concurrent package Handler AsyncTask Service AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso AndroidUniversalImageLoader AndroidAsync(Http), ION AndroidAnnotations Guava 커서관리 방법 없고, greenrobot/EventBus AsyncTask와 문제점 공유 otto
  • 32. Concurrent Programming Android Concurrent Programming Thread concurrent package Handler AsyncTask Service AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso AndroidUniversalImageLoader AndroidAsync(Http), ION AndroidAnnotations Guava 허니컴 이후 등장. compat을 이용해서 이전에도 사용이 가능하며 생명주기 변경시 스스로 처리함 단, ContentProvider 외에는 사용이 어려움 greenrobot/EventBus otto
  • 34. Concurrent Programming Third Party Libraries Thread concurrent package Handler AsyncTask Service AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso AndroidUniversalImageLoader AndroidAsync(Http), ION AndroidAnnotations Guava greenrobot/EventBus otto 네트워크, 이미지 Callback 기반
  • 35. Concurrent Programming Third Party Libraries Thread concurrent package Handler AsyncTask Service AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso AndroidUniversalImageLoader AndroidAsync(Http), ION AndroidAnnotations Guava greenrobot/EventBus otto 동기, 비동기 (async) 지원 RxJava의 Observable 지원
  • 36. Concurrent Programming Third Party Libraries Thread concurrent package Handler AsyncTask Service AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso AndroidUniversalImageLoader AndroidAsync(Http), ION AndroidAnnotations Guava greenrobot/EventBus otto
  • 37. Concurrent Programming Third Party Libraries Thread concurrent package Handler AsyncTask Service AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso AndroidUniversalImageLoader AndroidAsync(Http), ION AndroidAnnotations Guava greenrobot/EventBus otto Future
  • 38. Concurrent Programming Third Party Libraries Thread concurrent package Handler AsyncTask Service AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso AndroidUniversalImageLoader AndroidAsync(Http), ION AndroidAnnotations Guava greenrobot/EventBus otto @Background 어노테이션 내부적으로 ScheduledThreadPool을 활용
  • 39. Concurrent Programming Third Party Libraries Thread concurrent package Handler AsyncTask Service AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso AndroidUniversalImageLoader AndroidAsync(Http), ION AndroidAnnotations Guava greenrobot/EventBus otto ListenableFuture
  • 40. Concurrent Programming Third Party Libraries Thread concurrent package Handler AsyncTask Service AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso AndroidUniversalImageLoader AndroidAsync(Http), ION AndroidAnnotations Guava greenrobot/EventBus otto 이벤트 버스 RxJava로 대체 할 수 있음
  • 41. Concurrent Programming Third Party Libraries Thread 애플리케이션의 설계가 라이브러리 인터페이스에 의존적이 되는 것을 주의! 저마다 Http client, 이미지 캐싱, ThreadPool 관리 서로 다른 정책과 인터페이 concurrent package Handler AsyncTask Service 스를 가지고 있으므로, 중복 설정 및 불필요한 추상화를 주의! AsyncQueryHandler Loader Volley OkHttp, Retrofit, Picasso AndroidUniversalImageLoader AndroidAsync(Http), ION AndroidAnnotations Guava greenrobot/EventBus otto
  • 42. Concurrent Programming Android Event Sources KEY & TOUCH ACCELEROMETER GRAVITY GYROSCOPE LIGHT MAGNETIC ORIENTATION LOCATION PRESSURE
  • 43. Parallel tasks䯽 Concurrently executing tasks 멀티 태스크 Sequencial tasks䯽 One after another Request Task A Task B Task C Request 반드시 순서대로 실행 되어 야 하는 태스크 묶음 Task A Task B Task C Result Result
  • 44. 흔한 로그인 시나리오 1. Auth 2. Token 3. Login 4. Result 5. Request 6. Image Login with 순서대로 실행 되어야 함
  • 45. Sequencial tasks 순서를 갖는 작업들 UI Thread Req Resp Background TASK A TASK B TASK C
  • 46. Sequencial tasks 특히, Volley Callback 만을 지원하는 라이브러리 사용시 불필요한 UI 쓰레드 점유 UI Thread Req Resp Background TASK A TASK B TASK C
  • 47. Sequencial tasks 구현 방식 • Nested Callbacks • Future combination • SingleThreadExecutor • Handler + Looper Callback hell을 해결 할 수 있지만, 소스 네비게이션시 라인 점프는 늘어 날 수 있음. 하나의 쓰레드와 Task를 결합. 단, 오류 처리는 쉽지 않음 직접 워커를 만듦 커스텀 콜백 인터페이스를 정의 해야 함
  • 48. 흔한 로그인 시나리오 Callback hell requestFacebookLogin(new Callback() { public void onSuccess(Result result) { ... } });
  • 49. 흔한 로그인 시나리오 Callback hell requestFacebookLogin(new Callback() { public void onSuccess(Result result) { String facebookId = result.getFacebookId(); requestLogin(facebookId, new Callback() { ... }); } });
  • 50. 흔한 로그인 시나리오 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배씩 증가;;
  • 51. 흔한 로그인 시나리오 재시도 전략 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에 예외가 발생한 작업을 재시도 하고 싶을 땐? @#!%
  • 52. 흔한 로그인 시나리오 페이스북 로그인 > 앱 서버 로그인 > 초기 데이터 요청 > 오류 처리 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를 통해 유저에게 알리고 싶은데, “나는 누구 여긴 어디?”
  • 53. Parallel tasks䯽 Concurrently executing tasks 멀티 태스크 Sequencial tasks䯽 One after another 태스크간의 의존성이 없어, 동시 에 실행 될 수 있음. 그러나, 우리는 UI 프로그래머 Request Task A Task B Task C Request Task A Task B Task C Result Result
  • 54. 흔한 컨텐츠 공유 시나리오
  • 55. 흔한 컨텐츠 공유 시나리오 1. Req 1. Req 1. Req 1. Req
  • 56. 흔한 컨텐츠 공유 시나리오 1. Req 2. Resp 1. Req 2. Resp 1. Req 2. Resp 1. Req 2. Resp
  • 57. Parellel Tasks 동시에 수행 해야 하는 작업들 작업이 끝나는 시간은 모두 다를 수 있음. 모든 작업이 끝났을 때, UI에 반영하고 싶은데… UI Thread Login Data Thread A Data latency Thread B Thread C Data latency Data latency
  • 58. 흔한 컨텐츠 공유 시나리오 1. Req 2. Resp 1. Req 2. Resp 1. Req 2. Resp 1. Req 2. Resp 작업이 완료䯽 되었습니다.
  • 59. Parellel Tasks 구현 방식 각각의 태스크를 수행하고 flag를 통해 결과를 취합 • Creating Multiple Threads • CountDownLatch, MultiThreadExecutor (Thread Pool) 요청이 많은 경우 쓰레드 풀을 이용 concurrent 패키지의 CountDownLatch
  • 60. Composed Tasks 순차 + 병렬 Request Task A Task B Task C Task A Task B Task B Result 앱을 통해 사진과 글을 포스팅 (순차 태스크) 포스팅한 글을 SNS에 공유 (병렬 태스크)
  • 61. 이런거 없나? 어떤 데이터가 있는데…䯽 어떤 쓰레드에서 수행하고,䯽 필요한 데이터만 걸러내고,䯽 데이터를 어떻게 변환하고,䯽 오류 발생시에는 어떻게 대응할지,䯽 어떤 쓰레드에서 결과를 받을지,䯽 시작하면,䯽 ! 필요한 경우 취소 할 수 있어야 한다.䯽 ! 테스트도 쉬워야겠고!䯽 유추 가능한 것은 생략 할 수 있으면 좋겠다.
  • 62. 이런거 없나? observable䯽 어떤 쓰레드에서 수행하고,䯽 필요한 데이터만 걸러내고,䯽 데이터를 어떻게 변환하고,䯽 오류 발생시에는 어떻게 대응할지,䯽 어떤 쓰레드에서 결과를 받을지,䯽 시작하면,䯽 ! 필요한 경우 취소 할 수 있어야 한다.䯽 ! 테스트도 쉬워야겠고!䯽 유추 가능한 것은 생략 할 수 있으면 좋겠다.
  • 63. 이런거 없나? observable䯽 .subscribeOn(background)䯽 필요한 데이터만 걸러내고,䯽 데이터를 어떻게 변환하고,䯽 오류 발생시에는 어떻게 대응할지,䯽 어떤 쓰레드에서 결과를 받을지,䯽 시작하면,䯽 ! 필요한 경우 취소 할 수 있어야 한다.䯽 ! 테스트도 쉬워야겠고!䯽 유추 가능한 것은 생략 할 수 있으면 좋겠다.
  • 64. 이런거 없나? observable䯽 .subscribeOn(background)䯽 .filter(paidUser())䯽 데이터를 어떻게 변환하고,䯽 오류 발생시에는 어떻게 대응할지,䯽 어떤 쓰레드에서 결과를 받을지,䯽 시작하면,䯽 ! 필요한 경우 취소 할 수 있어야 한다.䯽 ! 테스트도 쉬워야겠고!䯽 유추 가능한 것은 생략 할 수 있으면 좋겠다.
  • 65. 이런거 없나? observable䯽 .subscribeOn(background)䯽 .filter(paidUser())䯽 .map(stringToJson())䯽 오류 발생시에는 어떻게 대응할지,䯽 어떤 쓰레드에서 결과를 받을지,䯽 시작하면,䯽 ! 필요한 경우 취소 할 수 있어야 한다.䯽 ! 테스트도 쉬워야겠고!䯽 유추 가능한 것은 생략 할 수 있으면 좋겠다.
  • 66. 이런거 없나? observable䯽 .subscribeOn(background)䯽 .filter(paidUser())䯽 .map(stringToJson())䯽 .doOnError(handleError())䯽 어떤 쓰레드에서 결과를 받을지,䯽 시작하면,䯽 ! 필요한 경우 취소 할 수 있어야 한다.䯽 ! 테스트도 쉬워야겠고!䯽 유추 가능한 것은 생략 할 수 있으면 좋겠다.
  • 67. 이런거 없나? observable䯽 .subscribeOn(background)䯽 .filter(paidUser())䯽 .map(stringToJson())䯽 .doOnError(handleError())䯽 .observeOn(mainThread)䯽 시작하면,䯽 ! 필요한 경우 취소 할 수 있어야 한다.䯽 ! 테스트도 쉬워야겠고!䯽 유추 가능한 것은 생략 할 수 있으면 좋겠다.
  • 68. 이런거 없나? observable䯽 .subscribeOn(background)䯽 .filter(paidUser())䯽 .map(stringToJson())䯽 .doOnError(handleError())䯽 .observeOn(mainThread)䯽 .subscribe() -> subscription䯽 ! 필요한 경우 취소 할 수 있어야 한다.䯽 ! 테스트도 쉬워야겠고!䯽 유추 가능한 것은 생략 할 수 있으면 좋겠다.
  • 69. 이런거 없나? observable䯽 .subscribeOn(background)䯽 .filter(paidUser())䯽 .map(stringToJson())䯽 .doOnError(handleError())䯽 .observeOn(mainThread)䯽 .subscribe() -> subscription䯽 ! subscription.unsubscribe()䯽 ! 테스트도 쉬워야겠고!䯽 유추 가능한 것은 생략 할 수 있으면 좋겠다.
  • 70. 이런거 없나? observable䯽 .subscribeOn(background)䯽 .filter(paidUser())䯽 .map(stringToJson())䯽 .doOnError(handleError())䯽 .observeOn(mainThread)䯽 .subscribe() -> subscription䯽 ! subscription.unsubscribe()䯽 ! ! assert…(paidUser())䯽 assert…(stringToJson())䯽 assert…(handleError()) ! 유추 가능한 것은 생략 할 수 있으면 좋겠다.
  • 71. 이런거 없나? observable䯽 .subscribeOn(background)䯽 .filter(paidUser())䯽 .map(stringToJson())䯽 .doOnError(handleError())䯽 .observeOn(mainThread)䯽 .subscribe() -> subscription䯽 ! subscription.unsubscribe()䯽 ! !
  • 73. RxJava 로직에만 집중 테스트 용이성 가독성 이름짓기? 내가 작성하는 코드가 어떤 쓰레드에서 돌아갈지 지금 당장은 관심이 없어. 왜냐하면, 실제 사용 할 시점에서 지정하면 되니까. 모듈화가 쉽다 == 테스트하기 쉽다 메소드 체이닝, 왼쪽에서 오른쪽으로 읽자 코드가 하는 일은 코드 자체가 표현하도록 하자.
  • 74. Custom Events 3초 동안 입력이 없으면 추천 검색어를 제시
  • 75. Custom Events D 3초 동안 입력이 없으면 추천 검색어를 제시
  • 76. Custom Events D E V 3초 동안 입력이 없으면 추천 검색어를 제시
  • 77. Custom Events 1s D E V 3초 동안 입력이 없으면 추천 검색어를 제시
  • 78. Custom Events 1s 2s D E V 3초 동안 입력이 없으면 추천 검색어를 제시
  • 79. Custom Events 1s 2s 3s D E V dev 검색 요청 3초 동안 입력이 없으면 추천 검색어를 제시
  • 80. Custom Events 1s 2s 3s D E V dev 검색 요청 3초 동안 입력이 없으면 추천 검색어를 제시
  • 81. Custom Events Custom Events lastInputTime 0 0 0 3 D E V 1s 2s 3s Thread Callback 1. 쓰레드 만들고 2. 이벤트 발생 시간 기록 3. 마지막 이벤트와 현재 시간 비교 4. 설정 값 이상의 차이가 발생시 콜백 또는, 1. 수행할 태스크를 작성 2. 태스크 등록(postDelayed 사용) 3. 이벤트 발생시 등록 이벤트 취소 4. 등록 된 태스크가 수행되며 콜백
  • 82. 람다 안드로이드 스튜디오 사용시 코드 폴딩을 통해 간결하게 표현되는 놈?
  • 83. 람다 Runnable task = new Runnable(){ @Override public void run(){ System.out.println("Hello Lamba"); } }; Runnable task2 = () -> { System.out.println("Hello Lamba"); };
  • 84. 람다 인터페이스가 하나의 메소드를 호출하면 굳이 메소드의 이름을 적을 필요는 없으니 생략 Runnable task = new Runnable(){ @Override public void run(){ System.out.println("Hello Lamba"); } }; Runnable task2 = () -> { System.out.println("Hello Lamba"); };
  • 85. 람다 파라미터는 비었으니 빈 괄호를 넣어주자 Runnable task = new Runnable(){ @Override public void run(){ System.out.println("Hello Lamba"); } }; Runnable task2 = () -> { System.out.println("Hello Lamba"); };
  • 86. 람다 Runnable task = new Runnable(){ @Override public void run(){ System.out.println("Hello Lamba"); } }; Runnable task2 = () -> { System.out.println("Hello Lamba"); }; 화살표 나오면 람다식! 블럭 내의 내용은 그대로~
  • 87. 이클립스에서 람다 사용 Xtend Xtend -> 자바 클래스로 변환 • 안드로이드의 Swift Eclipse에서 만들었음에도 리팩토링 기능이 취약함. 프로젝트가 커질수록 컴파일 타임이 급격히 증가 자체적으로 Guava 활용. 테스트 작성시 코드를 • 람다식은 익명 클래스를 통해 구현함 IntelliJ에서는 그냥 텍스트파일 빌드 프로세스를 고민 할 필요가 있음. 극히 간결하게 유지 할 수 있음. 메소드 단위 테스트가 불편 • 자바코드로 컴파일 되므로 호환성 문제가 없음 • 함수형 프로그래밍의 특징을 상당부분 수용함 • Eclipse IDE 지원 단점: 호환성 끝판왕 자바와 스칼라의 중간 어디쯤
  • 88. 안드로이드 스튜디오에서 람다 사용 RetroLambda 스튜디오의 기본기능인 폴딩도 괜찮지만, 람다 사용이 조금 더 편함 바이트 코드 조작을 통한 람다 사용 • 암묵적 참조로 클래스 참조로 인한 메모리 문제가 없음
  • 89. 함수형 프로그래밍 외부에서 건드릴 수 없음! 람다식이 함수형 프로그래밍은 절대 아님!
  • 90. 함수형 프로그래밍의 특징 불 대수 x, y z 는 숫자이거나 집합 (x ∧ z) ∨ (y ∧ z) = (x ∨ y) ∧ z
  • 91. 함수형 프로그래밍의 특징 불 대수 (x ∧ z) ∨ (y ∧ z) = (x ∨ y) ∧ z 람다 대수 클래스가 함수라면! 람다 대수에 의해 연산 가능! (λx.(λx.x)) y # λx.y
  • 93. RxJava Callback => Observable onDraw(Canvas canvas) Observer<Canvas>
  • 94. RxJava Callback => Observable Subscriber<? super Canvas> canvasSubscriber; ! @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvasSubscriber.onNext(canvas); } RxJava를 통해 콜백을 마치 컬렉션 처럼 바꿔줌
  • 95. RxJava Callback => Observable 60fps Observable onDraw(Canvas canvas) Observer<Canvas> 이제 collection 처럼 사용가능
  • 96. RxJava Callback => Observable Observer<Canvas> Observable 함수형 특징을 가진 언어는 다들 비슷비슷 Java 8’s Stream RxJava’s Observable 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) )
  • 97. RxJava Callback => Observable sineValueObservable drawCircle() Zip canvasObservable 지퍼 맞음
  • 98. RxJava Callback => Observable sineValueObservable drawCircle() Zip canvasObservable 지퍼 맞음
  • 99. RxJava Callback => Observable sineValueObservable drawCircle() Zip canvasObservable 지퍼 맞음
  • 100. RxJava Callback => Observable canvasObservable sineValueObservable drawCircle() Zip 두 collection(obsavable)의 각각 요소를 하나씩 결합! 짝이 성사되면 그리기 수행!
  • 101. RxJava Callback => Observable canvasObservable sineValueObservable drawCircle() Zip 결과물 역시 Obserable 이므로, 추가적인 연산이 얼만든지 가능함~
  • 106. 너무 어려워요… 함수형 프로그래밍은 어려운게 아닙니다.䯽 ! 익숙해지는데 시간이 좀 걸릴 뿐입니다.䯽 ! Rx와 함수형이 만능은 아닙니다.䯽 ! 칼퇴근을 보장하진 못하지만,䯽 ! 품질은 높아지고, 스트레스는 낮아집니다.䯽 ! 어렵게 느껴지면, 금요일 라 스칼라 코딩단에 구경오세요䯽 ! 같이 고민해봐요.䯽 ! …안드로이드 개발자 항시 대기 䯽 !
  • 108. RxJava 1. RxJava란?䯽 ! 2. RxJava(Thread, 이벤트 합성, 시간 관리, Subject, 예외 관리)䯽 ! 3. RxJava With MVVM䯽 !
  • 109. RxJava란? Excel䯽 - 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.䯽 ! ! A B C 1 2 10 20 30 = A1+A2
  • 110. RxJava란? Excel䯽 - 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.䯽 ! ! A B C 1 2 10 30 = A1+A2
  • 111. RxJava란? Excel䯽 - 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.䯽 ! ! A B C 1 2 10 30 = A1+A2 30
  • 112. RxJava란? Excel䯽 - 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.䯽 ! ! A B C 1 2 10 = A1+A2 30
  • 113. RxJava란? Excel䯽 - 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.䯽 ! ! A B C 1 2 10 = A1+A2 30 40
  • 114. RxJava - Observable, Observer란? Observable - 관측 가능한 값의 흐름를 나타내는 객체 (생산자)䯽 Observer - 값의 흐름를 받는 객체 (소비자)䯽 ! Observable Observer Button Click String Network Byte[] Keyboard Text View Alert Image View Input Text Error Image String Visibility Image Event
  • 115. RxJava - Observable, Observer란? Observable - 관측 가능한 값의 흐름를 나타내는 객체 (생산자)䯽 - subscribe 함수를 통해 구독이 가능하며, 구독자에게 값을 흐름을 알려준다.䯽 ! Observer - 값의 흐름를 받는 객체 (소비자)䯽 - Observable의 값의 흐름에 따라 onNext, onError, onCompelete를 호출 받는다.䯽 ! OnNext OnComplete OnError
  • 116. RxJava - Observable, Observer란? eventSource.subscribe((event)-> { // some action. } ); Observable Observer
  • 117. RxJava - subscribe/unsubscribe subscribe / unsubcribe䯽 - subscribe 를 통하여 Observable의 값의 변화를 구독하고,䯽 unsubscribe를 통해 구독을 해지한다.䯽 ! ! Button Function View Observable! (Operation! or! Producer) Observable! (Operation) Observer
  • 118. RxJava - subscribe/unsubscribe subscribe / unsubcribe䯽 - subscribe 를 통하여 Observable의 값의 변화를 구독하고,䯽 unsubscribe를 통해 구독을 해지한다.䯽 ! ! Button onSubscribe() Function subscribe() View Observable! (Operation! or! Producer) Observable! (Operation) Observer
  • 119. RxJava - subscribe/unsubscribe subscribe / unsubcribe䯽 - subscribe 를 통하여 Observable의 값의 변화를 구독하고,䯽 unsubscribe를 통해 구독을 해지한다.䯽 ! ! Button Function View Observable! (Operation! or! Producer) Observable! (Operation) Observer onSubscribe() subscribe() onNext() onNext()
  • 120. RxJava - subscribe/unsubscribe subscribe / unsubcribe䯽 - subscribe 를 통하여 Observable의 값의 변화를 구독하고,䯽 unsubscribe를 통해 구독을 해지한다.䯽 ! ! Button Function View Observable! (Operation! or! Producer) Observable! (Operation) Observer onSubscribe() subscribe() onNext() onNext() . . . . . .
  • 121. RxJava - subscribe/unsubscribe subscribe / unsubcribe䯽 - subscribe 를 통하여 Observable의 값의 변화를 구독하고,䯽 unsubscribe를 통해 구독을 해지한다.䯽 ! ! Button Function View Observable! (Operation! or! Producer) Observable! (Operation) Observer onSubscribe() subscribe() onNext() onNext() . . . . . . onNext() onNext()
  • 122. RxJava - subscribe/unsubscribe subscribe / unsubcribe䯽 - subscribe 를 통하여 Observable의 값의 변화를 구독하고,䯽 unsubscribe를 통해 구독을 해지한다.䯽 ! ! Button Function View Observable! (Operation! or! Producer) Observable! (Operation) Observer onSubscribe() subscribe() onNext() onNext() . . . . . . onNext() onNext() onComplete() onComplete()
  • 123. RxJava - subscribe/unsubscribe subscribe / unsubcribe䯽 - subscribe 를 통하여 Observable의 값의 변화를 구독하고,䯽 unsubscribe를 통해 구독을 해지한다.䯽 ! ! Button Function View Observable! (Operation! or! Producer) Observable! (Operation) Observer onSubscribe() subscribe() onNext() onNext() . . . . . . onNext() onNext() onComplete() onComplete() unsubscribe() unsubscribe()
  • 124. RxJava - map 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 TextView에 출력하는 시나리오 EditText Function TextView
  • 125. RxJava - map 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 TextView에 출력하는 시나리오 EditText Function TextView Text A fun(x) TextA-1
  • 126. RxJava - map 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 TextView에 출력하는 시나리오 EditText Function TextView Text B fun(x) TextB-1 Text A fun(x) TextA-1
  • 127. RxJava - map 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 TextView에 출력하는 시나리오 EditText Function TextView Text B fun(x) TextB-1 Text C fun(x) TextC-1 Text A fun(x) TextA-1
  • 128. RxJava - map map䯽 - 전달되는 값에 함수를 적용해서 새로운 값을 만들어냄 䯽 ! ! eventSource.map((value) -> {return fun(value);}) .subscribe((result) -> { ! // show result. });
  • 129. RxJava - flatMap 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 EditText Async Function TextView
  • 130. RxJava - flatMap 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 EditText Async Function TextView Text A
  • 131. RxJava - flatMap 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 EditText Async Function TextView Text A fun(x)
  • 132. RxJava - flatMap 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 EditText Async Function TextView fun(x) TextA-1 Text A
  • 133. RxJava - flatMap 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 EditText Async Function TextView Text A Text B fun(x) TextA-1
  • 134. RxJava - flatMap 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 EditText Async Function TextView fun(x) Text B TextA-1 Text A fun(x)
  • 135. RxJava - flatMap 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 EditText Async Function TextView fun(x) TextA-1 Text A fun(x) TextB-1 Text B
  • 136. RxJava - flatMap 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 EditText Async Function TextView fun(x) Text B Text C TextA-1 Text A fun(x) TextB-1
  • 137. RxJava - flatMap 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 EditText Async Function TextView fun(x) TextA-1 Text A fun(x) Text C TextB-1 Text B fun(x)
  • 138. RxJava - flatMap 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 EditText Async Function TextView fun(x) TextA-1 Text A fun(x) TextB-1 Text B fun(x) TextC-1 Text C
  • 139. RxJava - flatMap flatmap䯽 - 미래에 0개 ~ n개의 결과를 반환하는 함수를 적용한다.䯽 ! ! eventSource.flatMap((value) -> {return longlongFunc(value);}) .subscribe((Result) -> { ! // show result. ! }); Observable
  • 141. RxJava - Scheduler 이미지 다운로드 시나리오䯽 - 버튼을 클릭하면 이미지를 다운받아 표시하는 예제 UI Thread IO Thread UI Thread Click Image Image
  • 142. RxJava - Scheduler subscribeOn - 비동기 결과값을 가져오는 쓰레드를 결정한다 䯽 observeOn - 결과 값을 처리할 쓰레드를 결정한다. ClickEvents.flatMap((event) -> { return asyncDownloadImage(params) .subscribeOn(Schedulers.io()); }) .observeOn(AndroidSchedulers.mainThread()) .subscribe((image) -> { // show result. });
  • 143. RxJava - Scheduler observeOn䯽 - 결과 값을 처리할 쓰레드를 결정한다. Event observeOn(MainThreadScheduler) Thread Main Thread
  • 144. RxJava - Scheduler subscribeOn䯽 - 비동기 결과값을 가져오는 쓰레드를 결정한다. subscribeOn(IOThreadScheduler) IO Thread Event IO Thread
  • 145. RxJava - Scheduler Schedulers.computation()䯽 - 단순 연산을 처리하는 Thread들의 Pool로 구성된 Scheduler.䯽 ! Schedulers.io()䯽 - IO처리를 담당하는 Thread들의 Pool로 구성된 Scheduler.䯽 - 필요에 따라 자동으로 Pool의 크기를 늘리거나 줄인다.䯽 ! Schedulers.newThread()䯽 - 새로운 쓰레드를 만드는 Scheduler.䯽
  • 146. RxJava - Scheduler AndroidSchedulers.mainThread( )䯽 - Android의 Main Thread에서 작업을 수행한다.䯽 ! AndroidSchedulers.handlerThread(Handler handler)䯽 - 특정 Thread를 사용하는 Handler이용하는 Scheduler를 생성한다.䯽 ! Schedulers.from(Executor executor)䯽 - 특정 Executor를 사용하는 Scheduler를 생성한다.䯽 ! !
  • 148. RxJava - combineLatest, merge combineLatest䯽 - Observable 들의 이벤트들 중 가장 최신 이벤트 값을 합성해서 사용한다.䯽 ! Observable.combineLatest(color, shape, new Func2<Color, Shape, Image>() { @Override public Image call(Color color, Shape shape) { return image.createFrom(color, shape); } } );
  • 149. RxJava - combineLatest, merge combineLatest䯽 - Observable 들의 중 가장 최신의 이벤트 값을 합성한다.䯽 ! Color combineLatest( ) Shape Image
  • 150. RxJava - combineLatest, merge combineLatest䯽 - Observable 들의 중 가장 최신의 이벤트 값을 합성한다.䯽 ! Color combineLatest( ) 1 Shape Image
  • 151. RxJava - combineLatest, merge combineLatest䯽 - Observable 들의 중 가장 최신의 이벤트 값을 합성한다.䯽 ! Color combineLatest( ) 1 Shape Image 2 2
  • 152. RxJava - combineLatest, merge combineLatest䯽 - Observable 들의 중 가장 최신의 이벤트 값을 합성한다.䯽 ! Color combineLatest( ) 1 Shape Image 2 2 3 3
  • 153. RxJava - combineLatest, merge combineLatest䯽 - Observable 들의 중 가장 최신의 이벤트 값을 합성한다.䯽 ! Color combineLatest( ) 1 Shape Image 2 2 3 4 3 4
  • 154. RxJava - combineLatest, merge merge䯽 - Observable 들의 이벤트들을 합성해서 사용한다.䯽 ! Observable<Void> clickEvnets = Observable.merge(clickEventFromButtonA, clickEventFromButtonB);
  • 155. RxJava - combineLatest, merge merge䯽 - Observable 들의 이벤트들을 합성해서 사용한다.䯽 ! Login Button merge( ) Enter Key Login Event
  • 156. RxJava - combineLatest, merge merge䯽 - Observable 들의 이벤트들을 합성해서 사용한다.䯽 ! Login Button merge( ) Login Event 1 1 Enter Key
  • 157. RxJava - combineLatest, merge merge䯽 - Observable 들의 이벤트들을 합성해서 사용한다.䯽 ! Login Button merge( ) Login Event 1 1 Enter Key 2 2
  • 158. RxJava - combineLatest, merge merge䯽 - Observable 들의 이벤트들을 합성해서 사용한다.䯽 ! Login Button merge( ) Login Event 1 1 Enter Key 3 2 2 3
  • 159. RxJava - combineLatest, merge merge䯽 - Observable 들의 이벤트들을 합성해서 사용한다.䯽 ! Login Button merge( ) Login Event 1 1 Enter Key 3 2 4 2 3 4
  • 161. RxJava - Time 예제) throttleWithTimeout䯽 - 자동 완성 기능䯽 ! // 기본 변수 설정 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));
  • 162. RxJava - Time delay䯽 - 모든 이벤트를 주어진 시간만큼 지연한다.䯽 ! Observer delay( )
  • 163. RxJava - Time delay䯽 - 모든 이벤트를 주어진 시간만큼 지연한다.䯽 ! 1 Observer delay( )
  • 164. RxJava - Time delay䯽 - 모든 이벤트를 주어진 시간만큼 지연한다.䯽 ! 1 Observer 1 delay( )
  • 165. RxJava - Time delay䯽 - 모든 이벤트를 주어진 시간만큼 지연한다.䯽 ! 1 2 Observer 1 delay( )
  • 166. RxJava - Time delay䯽 - 모든 이벤트를 주어진 시간만큼 지연한다.䯽 ! 1 2 Observer 1 2 delay( )
  • 167. RxJava - Time delay䯽 - 모든 이벤트를 주어진 시간만큼 지연한다.䯽 ! 1 2 3 Observer 1 2 delay( )
  • 168. RxJava - Time delay䯽 - 모든 이벤트를 주어진 시간만큼 지연한다.䯽 ! 1 2 3 Observer 1 2 3 delay( )
  • 169. RxJava - Time throttleFirst䯽 - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 ! Observer throttleFirst( )
  • 170. RxJava - Time throttleFirst䯽 - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 ! Observer throttleFirst( ) 1 1
  • 171. RxJava - Time throttleFirst䯽 - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 ! Observer throttleFirst( ) 1 1
  • 172. RxJava - Time throttleFirst䯽 - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 ! Observer throttleFirst( ) 1 2 1
  • 173. RxJava - Time throttleFirst䯽 - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 ! Observer throttleFirst( ) 1 1 2 3 3
  • 174. RxJava - Time throttleFirst䯽 - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 ! Observer throttleFirst( ) 1 1 2 3 3
  • 175. RxJava - Time throttleFirst䯽 - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 ! Observer throttleFirst( ) 1 1 2 3 4 3
  • 176. RxJava - Time throttleFirst䯽 - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 ! Observer 3 5 throttleFirst( ) 1 1 3 5 2 4
  • 177. RxJava - Time throttleFirst䯽 - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 ! Observer 3 5 throttleFirst( ) 1 1 3 5 2 4
  • 178. RxJava - Time throttleWithTimeout䯽 - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 ! Observer throttleWithTimeout( )
  • 179. RxJava - Time throttleWithTimeout䯽 - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 ! Observer throttleWithTimeout( ) 1
  • 180. RxJava - Time throttleWithTimeout䯽 - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 ! Observer throttleWithTimeout( ) 1
  • 181. RxJava - Time throttleWithTimeout䯽 - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 ! Observer throttleWithTimeout( ) 1 1
  • 182. RxJava - Time throttleWithTimeout䯽 - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 ! Observer throttleWithTimeout( ) 1 2 1
  • 183. RxJava - Time throttleWithTimeout䯽 - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 ! Observer throttleWithTimeout( ) 1 2 1
  • 184. RxJava - Time throttleWithTimeout䯽 - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 ! Observer 1 2 3 throttleWithTimeout( ) 1
  • 185. RxJava - Time throttleWithTimeout䯽 - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 ! Observer 1 2 3 throttleWithTimeout( ) 1
  • 186. RxJava - Time throttleWithTimeout䯽 - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 ! Observer 1 2 3 4 throttleWithTimeout( ) 1
  • 187. RxJava - Time throttleWithTimeout䯽 - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 ! Observer 1 2 3 4 throttleWithTimeout( ) 1
  • 188. RxJava - Time throttleWithTimeout䯽 - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 ! Observer 1 2 3 4 1 4 throttleWithTimeout( )
  • 190. RxJava - Subject(Observable + Observer) BehaviorSubject를 사용한 SharedPreferences 예제䯽 ! 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));
  • 191. RxJava - Subject(Observable + Observer) BehaviorSubject䯽 ! ! ! BehaviorSubject Observer1 Observer2
  • 192. RxJava - Subject(Observable + Observer) BehaviorSubject䯽 ! ! 1 ! BehaviorSubject Observer1 Observer2
  • 193. RxJava - Subject(Observable + Observer) BehaviorSubject䯽 ! ! 1 ! subscribe() BehaviorSubject Observer1 Observer2
  • 194. RxJava - Subject(Observable + Observer) BehaviorSubject䯽 ! ! 1 ! subscribe() 1 BehaviorSubject Observer1 Observer2
  • 195. RxJava - Subject(Observable + Observer) BehaviorSubject䯽 ! ! ! 1 2 2 subscribe() 1 BehaviorSubject Observer1 Observer2
  • 196. RxJava - Subject(Observable + Observer) BehaviorSubject䯽 ! ! ! 1 2 2 subscribe() 1 subscribe() BehaviorSubject Observer1 Observer2
  • 197. RxJava - Subject(Observable + Observer) BehaviorSubject䯽 ! ! ! 1 2 2 subscribe() 1 2 subscribe() BehaviorSubject Observer1 Observer2
  • 198. RxJava - Subject(Observable + Observer) BehaviorSubject䯽 ! ! ! 1 2 2 subscribe() 1 2 3 3 3 subscribe() BehaviorSubject Observer1 Observer2
  • 199. RxJava - Subject(Observable + Observer) PublishSubject䯽 ! ! PublishSubject Observer1 Observer2
  • 200. RxJava - Subject(Observable + Observer) PublishSubject䯽 ! ! 1 PublishSubject Observer1 Observer2
  • 201. RxJava - Subject(Observable + Observer) PublishSubject䯽 ! ! 1 subscribe() PublishSubject Observer1 Observer2
  • 202. RxJava - Subject(Observable + Observer) PublishSubject䯽 ! ! 1 2 2 subscribe() PublishSubject Observer1 Observer2
  • 203. RxJava - Subject(Observable + Observer) PublishSubject䯽 ! ! 1 2 2 subscribe() subscribe() PublishSubject Observer1 Observer2
  • 204. RxJava - Subject(Observable + Observer) PublishSubject䯽 ! ! 1 2 subscribe() 3 2 3 3 subscribe() PublishSubject Observer1 Observer2
  • 205. RxJava - Subject(Observable + Observer) Replay Subject䯽 ! ! ReplaySubject Observer1 Observer2
  • 206. RxJava - Subject(Observable + Observer) Replay Subject䯽 ! ! 1 ReplaySubject Observer1 Observer2
  • 207. RxJava - Subject(Observable + Observer) Replay Subject䯽 ! ! 1 subscribe() ReplaySubject Observer1 Observer2
  • 208. RxJava - Subject(Observable + Observer) Replay Subject䯽 ! ! 1 subscribe() ReplaySubject Observer1 Observer2 1
  • 209. RxJava - Subject(Observable + Observer) Replay Subject䯽 ! ! 1 2 2 subscribe() ReplaySubject Observer1 Observer2 1
  • 210. RxJava - Subject(Observable + Observer) Replay Subject䯽 ! ! 1 2 2 subscribe() subscribe() ReplaySubject Observer1 Observer2 1
  • 211. RxJava - Subject(Observable + Observer) Replay Subject䯽 ! ! 1 2 2 subscribe() subscribe() ReplaySubject Observer1 Observer2 1 1
  • 212. RxJava - Subject(Observable + Observer) Replay Subject䯽 ! ! 1 2 2 subscribe() subscribe() ReplaySubject Observer1 Observer2 1 1 2
  • 213. RxJava - Subject(Observable + Observer) Replay Subject䯽 ! ! 1 2 2 subscribe() subscribe() ReplaySubject Observer1 Observer2 1 1 2 3 3 3
  • 215. RxJava - Error Handling doOnError䯽 - 실패한 경우, 예외를 처리하는 기능을 수행할 수 있습니다.䯽 ! GetDataFromNetwork() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnError((e) -> {showError(e);}) .subscribe((img) -> {showImage(img);}) 1 Observer 1 X
  • 216. RxJava - Error Handling doOnError䯽 - 실패한 경우, 예외를 처리하는 기능을 수행할 수 있습니다.䯽 ! GetDataFromNetwork() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnError((e) -> {showError(e);}) .subscribe((img) -> {showImage(img);}) 1 Observer 1 X Error Handling
  • 217. RxJava - Error Handling retry䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 ! GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry() Observer retry()
  • 218. RxJava - Error Handling retry䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 ! GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry() Observer retry() 1 1
  • 219. RxJava - Error Handling retry䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 ! GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry() Observer retry() 1 X 1
  • 220. RxJava - Error Handling retry䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 ! GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry() Observer retry() 1 X 1
  • 221. RxJava - Error Handling retry䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 ! GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry() Observer retry() 1 X 1 3 3
  • 222. RxJava - Error Handling retry(int n)䯽 - 실패한 경우 자동으로 n회 재시도 합니다.䯽 ! GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry(1) Observer retry(1)
  • 223. RxJava - Error Handling retry(int n)䯽 - 실패한 경우 자동으로 n회 재시도 합니다.䯽 ! GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry(1) Observer retry(1) 1 1
  • 224. RxJava - Error Handling retry(int n)䯽 - 실패한 경우 자동으로 n회 재시도 합니다.䯽 ! GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry(1) Observer retry(1) 1 X 1
  • 225. RxJava - Error Handling retry(int n)䯽 - 실패한 경우 자동으로 n회 재시도 합니다.䯽 ! GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry(1) Observer retry(1) 1 X 1
  • 226. RxJava - Error Handling retry(int n)䯽 - 실패한 경우 자동으로 n회 재시도 합니다.䯽 ! GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry(1) Observer retry(1) 1 X 1 2 2
  • 227. RxJava - Error Handling retry(int n)䯽 - 실패한 경우 자동으로 n회 재시도 합니다.䯽 ! 2 X GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry(1) Observer retry(1) 1 X 1 2 X
  • 228. RxJava - Error Handling retryWhen(Observable)䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 ! Observer retryWhen()
  • 229. RxJava - Error Handling retryWhen(Observable)䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 ! Observer retryWhen() 1 1
  • 230. RxJava - Error Handling retryWhen(Observable)䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 ! Observer retryWhen() 1 X 1
  • 231. RxJava - Error Handling retryWhen(Observable)䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 ! Observer retryWhen() 1 X 1 delay(3, SECODS)
  • 232. RxJava - Error Handling retryWhen(Observable)䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 ! Observer retryWhen() 1 X 1 delay(3, SECODS)
  • 233. RxJava - Error Handling retryWhen(Observable)䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 ! Observer retryWhen() 1 X 1 3 3 delay(3, SECODS)
  • 234. RxJava - Error Handling retryWhen(Observable)䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 ! Observer retryWhen() ! GetDataFromNetwork() 1 X 1 3 3 .subscribeOn(Schedulers.io()) .retryWhen((observable) -> delay(3, SECODS) { // 3초마다 재시도 return observable.delay(3, TimeUnit.SECONDS); })
  • 236. RxJava - MVVM Loading Indicator 예제䯽 버튼을 클릭하면 다운로드가 완료될 때까지 Loading indicator를 표시한다.䯽 ! ! // 버튼 클릭 이벤트 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); )}
  • 237. RxJava - MVVM Loading Indicator 예제䯽 버튼을 클릭하면 다운로드가 완료될 때까지 Loading indicator를 표시한다.䯽 ! ! // 버튼 클릭 이벤트 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
  • 238. RxJava - MVVM Model View User Info String String Login Info String Profile Image Text View Alert Image View Input Text Error Image Image Visibility Image Event View Model 운영체제에䯽 의존적 운영체제에䯽 독립적
  • 239. RxJava - MVVM Model View User Info String String Login Info String Profile Image Text View Alert Image View Input Text Error Image Image Visibility Image Event View Model 재사용이䯽 어려움 재사용이 원활함
  • 240. RxJava - MVVM Model View User Info String String Login Info String Profile Image Text View Alert Image View Input Text Error Image Image Visibility Image Event View Model 테스트 불 가능 코드 테스트 가능 코드 연결 코드
  • 241. 결론
  • 242. 왜 Reactive Programming 인가? 프로그램의 일관성을 유지하는 통일된 방식이 필요䯽 - Event, Thread, 시간, Exception을 처리하기에는 Callback은 조합이 어렵다.䯽 - 그러므로 개개인이 각각의 방식으로 조합하여 복잡성이 증대된다.䯽 ! ! 단순 객체지향으로는 큰 프로그램을 만들기 어렵다.䯽 - 객체지향은 내부의 상세한 구현을 숨긴다.䯽 - 이로인해 잘 만들지 않으면 기대와 다른 동작들로 인해 복잡도가 증가한다.䯽 - 이를 해결하기 위해 객체가 객체를 감싸고 또다시 감싸는 등의 문제가 발생한다.䯽 ! !
  • 243. 왜 Reactive Programming 인가? 프로그램의 일관성을 유지하는 통일된 방식이 필요䯽 - Event, Thread, 시간, Exception을 처리하기에는 Callback은 조합이 어렵다.䯽 - 그러므로 개개인이 각각의 방식으로 조합하여 복잡성이 증대된다.䯽 ! ! 단순 객체지향으로는 큰 프로그램을 만들기 어렵다.䯽 - 객체지향은 내부의 상세한 구현을 숨긴다.䯽 - 이로인해 잘 만들지 않으면 기대와 다른 동작들로 인해 복잡도가 증가한다.䯽 - 이를 해결하기 위해 객체가 객체를 감싸고 또다시 감싸는 등의 문제가 발생한다.䯽 ! ! 통일된 방식으로 Event, Thread, Time, Exception을 처리할 수 있는 방법 제공
  • 244. 왜 Reactive Programming 인가? 프로그램의 일관성을 유지하는 통일된 방식이 필요䯽 - Event, Thread, 시간, Exception을 처리하기에는 Callback은 조합이 어렵다.䯽 - 그러므로 개개인이 각각의 방식으로 조합하여 복잡성이 증대된다.䯽 ! ! 단순 객체지향으로는 큰 프로그램을 만들기 어렵다.䯽 - 객체지향은 내부의 상세한 구현을 숨긴다.䯽 - 이로인해 잘 만들지 않으면 기대와 다른 동작들로 인해 복잡도가 증가한다.䯽 - 이를 해결하기 위해 객체가 객체를 감싸고 또다시 감싸는 등의 문제가 발생한다.䯽 ! ! 통일된 방식으로 Event, Thread, Time, Exception을 처리할 수 있는 방법 제공 외부에 제공할 수 있는 읽기 전용의 Observable을 제공하며 내용을 감추지 않아도 됨
  • 245. 왜 Reactive Programming 인가? 보다 테스트하기 쉬운 구조가 필요하다.䯽 - 일반적인 구현에서는 가장 내부 깊은 곳에 View, Activity 등이 존재한다.䯽 - 이로 인해 테스트에서 View를 제거하지 못해 테스트가 힘들어진다.䯽
  • 246. 왜 Reactive Programming 인가? 보다 테스트하기 쉬운 구조가 필요하다.䯽 - 일반적인 구현에서는 가장 내부 깊은 곳에 View, Activity 등이 존재한다.䯽 - 이로 인해 테스트에서 View를 제거하지 못해 테스트가 힘들어진다.䯽 MVVM의 구조를 활용하여 OS 종속적인 부분을 최대한 배제하고 테스트할 수 있음