Skip to content

Latest commit

ย 

History

History
412 lines (248 loc) ยท 14.4 KB

RxAndroid.md

File metadata and controls

412 lines (248 loc) ยท 14.4 KB

RxAndroid

์•ˆ๋“œ๋กœ์ด๋“œ์˜ RxJava ํ™œ์šฉ

์ž‘์„ฑ์ž : ๋ฐ•ํƒœ์ž„

Present Time : 2018-09-20 (THU)

1. RxAndroid ์†Œ๊ฐœ

๊ธฐ์กด ์•ˆ๋“œ๋กœ์ด๋“œ ๊ฐœ๋ฐœ์—์„œ ๊ฐ€์žฅ ์–ด๋ ค์›€์„ ๊ฒช๋Š” ๋ฌธ์ œ ์ค‘ ํ•˜๋‚˜๋Š” ๋ณต์žกํ•œ ์Šค๋ ˆ๋“œ ์‚ฌ์šฉ์ด๋‹ค. ๋ณต์žกํ•œ ์Šค๋ ˆ๋“œ ์‚ฌ์šฉ์œผ๋กœ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ์•ˆ๋“œ๋กœ์ด๋“œ์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๋ฐ ์—๋Ÿฌ ํ•ธ๋“ค๋ง
  • ์ˆ˜๋งŽ์€ ํ•ธ๋“ค๋Ÿฌ์™€ ์ฝœ๋ฐฑ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•˜๋Š” ๋””๋ฒ„๊น… ๋ฌธ์ œ
  • 2๊ฐœ์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ํ›„ ๊ฒฐ๊ณผ๋ฅผ ํ•˜๋‚˜๋กœ ํ•ฉ์„ฑํ•˜๋Š” ์ž‘์—…
  • ์ด๋ฒคํŠธ ์ค‘๋ณต ์‹คํ–‰

์ˆ™๋ จ๋„ ๋†’์€ ๊ฐœ๋ฐœ์ž๋„ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ๋””๋ฒ„๊น…ํ•˜๋Š” ๋ฐ ๋งŽ์€ ์‹œ๊ฐ„์„ ํˆฌ์žํ•œ๋‹ค.

RxAndroid ๋Š” ์Šต๋“ํ•˜๊ธฐ ์–ด๋ ค์šด ๋ถ€๋ถ„๋„ ์žˆ์ง€๋งŒ ๊ธฐ์กด ์•ˆ๋“œ๋กœ์ด๋“œ ๊ฐœ๋ฐœ๊ณผ ๋น„๊ตํ–ˆ์„ ๋•Œ ์žฅ์ ์ด ๋งŽ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ง•์„ ํ†ตํ•ด ์•ž ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค€๋‹ค.

  • ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋กœ ๋ณต์žกํ•œ ๋ณ‘ํ–‰(concurrency) ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋น„๋™๊ธฐ ๊ตฌ์กฐ์—์„œ ์—๋Ÿฌ๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์‰ฝ๋‹ค.
  • ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ๋ฒ•๋„ ๋ถ€๋ถ„์ ์œผ๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

1.1 ๋ฆฌ์•กํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ API

RxAndroid๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ RxJava์˜ ๋ฆฌ์•กํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•œ๋‹ค. ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ ์ด์šฉํ•˜๋Š” ๋ฆฌ์•กํ‹ฐ๋ธŒ API์™€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ƒ๋‹นํžˆ ๋งŽ๋‹ค.

* ์•ˆ๋“œ๋กœ๋“œ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฆฌ์•กํ‹ฐ๋ธŒ API์™€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ) RxLifecycle, RxBinding, RxLocation, RxFit, RxWear, RxImagePicker, ReactiveNetwork, RxDataBinding ๋“ฑ

1.2 Android Studio Setting

gradle์˜ dependencies ๋ถ€๋ถ„์— RxAndroid ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

์ฐธ๊ณ  ) RxAndroid๋Š” RxJava์— ๋Œ€ํ•œ ์˜์กด์„ฑ์ด ์žˆ์–ด RxJava๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•„๋„ ๋˜์ง€๋งŒ, ์ตœ์‹  ๋ฒ„์ „์˜ RxJava๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋ช…์‹œํ•ด ์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
dependencies{
	// RxJava & RxAndroid
	implementation 'io.reactivex.rxjava2:rxjava:2.2.2'
	implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
	
	// RxLifecycle
	implementation 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.2'
	implementation 'com.trello.rxlifecycle2:rxlifecycle:2.2.2'
	implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.2'
}



2. RxAndroid ๊ธฐ๋ณธ

RxAndroid์˜ ๊ธฐ๋ณธ ๊ฐœ๋…์€ RxJava์™€ ๋™์ผํ•˜๋‹ค. RxJava์˜ ๊ตฌ์กฐ์— ์•ˆ๋“œ๋กœ์ด๋“œ์˜ ๊ฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณ€๊ฒฝํ•ด ๋†“์€ ๊ฒƒ์ด๋‹ค. ๋”ฐ๋ผ์„œ RxAndroid์˜ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ RxJava์˜ ๊ตฌ์„ฑ ์š”์†Œ์™€ ๊ฐ™๋‹ค.

  • Observable : ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐœํ–‰ํ•œ๋‹ค.
  • ๊ตฌ๋…์ž : Observable์—์„œ ๋ฐœํ–‰ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ๋…ํ•œ๋‹ค.
  • ์Šค์ผ€์ค„๋Ÿฌ : ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ํ†ตํ•ด์„œ Observable, ๊ตฌ๋…์ž๊ฐ€ ์–ด๋Š ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋ ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋Ÿฌํ•œ ๊ณผ์ •์„ ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋กœ ๋‚˜ํƒ€๋‚ด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

Observable๊ณผ ๊ตฌ๋…์ž๊ฐ€ ์—ฐ๊ฒฐ๋˜๋ฉด ์Šค์ผ€์ค„๋Ÿฌ์—์„œ ๊ฐ ์š”์†Œ๊ฐ€ ์‚ฌ์šฉํ•  ์Šค๋ ˆ๋“œ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ์ด๋‹ค. Observable์ด ์‹คํ–‰๋˜๋Š” ์Šค๋ ˆ๋“œ๋Š” subscribeOn() ํ•จ์ˆ˜์—์„œ ์„ค์ •ํ•˜๊ณ  ์ฒ˜๋ฆฌ๋œ ๊ฒฐ๊ณผ๋ฅผ onserveOn() ํ•จ์ˆ˜์— ์„ค์ •๋œ ์Šค๋ ˆ๋“œ๋กœ ๋ณด๋‚ด ์ตœ์ข… ์ฒ˜๋ฆฌํ•œ๋‹ค.

// 1. Observable ์ƒ์„ฑ
Observable.create()
  .subscribe();  // 2. ๊ตฌ๋…์ž ์ด์šฉ

  // 3. ์Šค์ผ€์ค„๋Ÿฌ ์ด์šฉ
  .subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())

2.1 RxAndroid์—์„œ ์ œ๊ณตํ•˜๋Š” ์Šค์ผ€์ค„๋Ÿฌ

์Šค์ผ€์ค„๋Ÿฌ ์ด๋ฆ„ ์„ค๋ช…
AndroidSchedulers.mainThread() ์•ˆ๋“œ๋กœ์ด๋“œ์˜ UI ์Šค๋ ˆ๋“œ์—์„œ ๋™์ž‘ํ•˜๋Š” ์Šค์ผ€์ค„๋Ÿฌ
HandlerScheduler.from(handler) ํŠน์ • ํ•ธ๋“ค๋Ÿฌ์— ์˜์กดํ•˜์—ฌ ๋™์ž‘ํ•˜๋Š” ์Šค์ผ€์ค„๋Ÿฌ

์•ˆ๋“œ๋กœ์ด๋“œ์˜ UI์Šค๋ ˆ๋“œ๋Š” ๋ฉ”์ธ์Šค๋ ˆ๋“œ๋ฅผ ๋œปํ•œ๋‹ค.

์Šค๋ ˆ๋“œ์™€ Handler์— ๊ด€๋ จํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ ๊ธ€์„ ์ฐธ๊ณ  [์Šคํ„ฐ๋”” 1ํšŒ์ฐจ Thread , Handler , Looper ์ฐธ๊ณ ]


2.2 TextView์— ํ…์ŠคํŠธ ์ถœ๋ ฅํ•ด๋ณด๊ธฐ - ์˜ˆ์ œ

2.2.1 create() ์‚ฌ์šฉ

Observer<String> observer = new DisposableObserver<String>() {
  @Override
  public void onNext(String s){
    textView.setText(s);
  }
  @Override
  public void onError(Throwable e) { }
  @Override
  public void onComplete() { }  
}

Observable.create(new ObservableOnSubscribe<String>(){
  @Override
  public void subscribe(ObservableEmitter<String> e) throws Exception{
    e.onNext("I'm student.");
    e.onComplete();
  }
}).subscribe(observer);

Observable.create() ๋กœ Observable ์„ ์ƒ์„ฑํ•ด 'I'm student.'(์ถœ๋ ฅํ•  ํ…์ŠคํŠธ) ๋ฅผ ์ž…๋ ฅ ๋ฐ›๊ณ  subscribe() ํ•จ์ˆ˜ ์•ˆ onNext() ํ•จ์ˆ˜์— ์ „๋‹ฌํ•œ๋‹ค.

onNext() ํ•จ์ˆ˜๋Š” ์ „๋‹ฌ๋œ ๋ฌธ์ž๋ฅผ ํ…์ŠคํŠธ๋ทฐ์— ์—…๋ฐ์ดํŠธ ํ•˜๋„๋ก ์ •์˜๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ,

์‹ค์ œ ๊ตฌ๋…์ž๋ฅผ subscribe(observer) ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋“ฑ๋กํ•˜๊ณ  ํ˜ธ์ถœํ•˜๋ฉด 'I'm student.' ๋ฅผ ํ…์ŠคํŠธ๋ทฐ์— ํ‘œ์‹œํ•œ๋‹ค.

2.2.2 create() ์‚ฌ์šฉ - ๋žŒ๋‹คํ‘œํ˜„์‹์œผ๋กœ ๋ณ€ํ˜•

Observable.<String> create(s->{
  s.onNext("I'm smart!");
  s.onComplete();
}).subscribe(o -> textView.setText(o));

์œ„ 2.2.1๊ณผ ๋น„๊ตํ•˜๋ฉด ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋žŒ๋‹ค ํ‘œํ˜„์‹์œผ๋กœ ๋ฐ”๊พธ๋ฉฐ ๋ฐ์ดํ„ฐ์˜ ํ๋ฆ„์ด ๋ช…ํ™•ํ•ด์ ธ ๊ฐ€๋…์„ฑ์ด ์ข‹์•„์กŒ๋‹ค.

์ „๋‹ฌ์ž๋Š” ๋ช…ํ™•ํ•œ ๋‹จ์–ด๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ด๋‹ˆ์…œ์„ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค.

2.2.3 just() ์‚ฌ์šฉ

Observable.just("I'm hungry.")
  .subscribe(textView::setText);

๋ฉ”์„œ๋“œ ๋ ˆํผ๋Ÿฐ์Šค ๋ฅผ ์ด์šฉํ•˜์—ฌ Observable์˜ ์ƒ์„ฑ ์ฝ”๋“œ๋ฅผ ๋‹จ์ˆœํ•˜๊ฒŒ ํ–ˆ๋‹ค.

์ฐธ๊ณ ) Observable ์˜ ์ƒ์„ฑ ๋ฐฉ๋ฒ•์€ ์›Œ๋‚™ ๋‹ค์–‘ํ•˜๊ณ  ๊ฐœ๋ฐœ์ž์˜ ์„ฑํ–ฅ์— ๋”ฐ๋ผ ์„ ํƒ์˜ ๊ธฐ์ค€์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋‹ค.



2.3 RxLifecycle ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

RxAndroid์—๋Š” RxLifecycle ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

์•ˆ๋“œ๋กœ์ด๋“œ์˜ Activity ์™€ Fragment ์˜ ๋ผ์ดํ”„ ์‚ฌ์ดํด์„ RxJava์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.

์•ˆ๋“œ๋กœ์ด๋“œ์™€ UI ๋ผ์ดํ”„ ์‚ฌ์ดํด์„ ๋Œ€์ฒดํ•œ๋‹ค๊ธฐ๋ณด๋‹ค ๊ตฌ๋…ํ•  ๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค. ์™„๋ฃŒํ•˜์ง€ ๋ชปํ•œ ๊ตฌ๋…์„ ์ž๋™์œผ๋กœ ํ•ด์ œ(dispose) ํ•œ๋‹ค.


2.3.1 RxLifecycle, ์™œ ์‚ฌ์šฉํ•˜์ฃ ?

Observable์€ ์•ˆ๋“œ๋กœ์ด๋“œ์˜ Context๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ ์œ ์ง€ํ•œ๋‹ค. onComplete(), onError() ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ๋‚ด๋ถ€์—์„œ ์ž๋™์œผ๋กœ unsubscribe() ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์•กํ‹ฐ๋น„ํ‹ฐ๊ฐ€ ๋น„์ •์ƒ์ ์œผ๋กœ ์ข…๋ฃŒ๋˜๋ฉด ๋ทฐ๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ์•กํ‹ฐ๋น„ํ‹ฐ๋Š” ์ข…๋ฃŒํ•ด๋„ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜์˜ ๋Œ€์ƒ์ด ๋˜์ง€ ๋ชปํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.

์ด๋•Œ ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๊ฐ€ RxLifecycle์„ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.


2.3.2 RxLifecycle ๋ผ์ดํ”„ ์‚ฌ์ดํด ์ปดํฌ๋„ŒํŠธ

RxLifecycle ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์•ˆ๋“œ๋กœ์ด๋“œ์˜ ๋ผ์ดํ”„ ์‚ฌ์ดํด์— ๋งž๊ฒŒ Observable ์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

์ปดํฌ๋„ŒํŠธ ์„ค๋ช…
RxActivity ์•กํ‹ฐ๋น„ํ‹ฐ์— ๋Œ€์‘
RxDialogFragment Native/Support ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ DialogFragment ์— ๋Œ€์‘
RxFragment Native/Support ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ Fragment ์— ๋Œ€์‘
RxPreferenceFragment PreferenceFragment์— ๋Œ€์‘
RxAppCompatActivity Support ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ DialogFragment์— ๋Œ€์‘
RxAppCompatDialogFragment Support ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ AppCompatDialogFragment์— ๋Œ€์‘
RxFragmentActivity Support ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ FragmentActivity์— ๋Œ€์‘

2.3.3 RxLifecycle ์‚ฌ์šฉํ•ด๋ณด๊ธฐ - ์˜ˆ์ œ

  • build.gradle ํŒŒ์ผ์˜ depencies์— ์ถ”๊ฐ€
dependencies{
	// RxLifecycle
	implementation 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.2'
	implementation 'com.trello.rxlifecycle2:rxlifecycle:2.2.2'
	implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.2'
}

Observable.interval()์„ ์ด์šฉํ•ด 1์ดˆ์— ํ•œ๋ฒˆ ๋กœ๊ทธ๋ฅผ ์ฐ๋‹ค๊ฐ€

ํ™”๋ฉด์ด ๋’ค๋กœ๊ฐ€ ์•กํ‹ฐ๋น„ํ‹ฐ๊ฐ€ ์ข…๋ฃŒ๋˜์–ด๋„ unsubscribe(๊ตฌ๋… ํ•ด์ œ)๋ฅผ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์ŠคํŠธ๋ฆผ์€ ๊ณ„์† ์œ ์ง€๋˜์–ด ๋กœ๊ทธ๊ฐ€ ๊ณ„์† ์ฐํžˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

Observable.interval(0,1,TimeUnit.SECONDS)
  .map(String::valueOf)
  .subscribe(s -> Lob.i("###",s));

compose() ํ•จ์ˆ˜๋กœ ๋ผ์ดํ”„ ์‚ฌ์ดํด์„ ๊ด€๋ฆฌํ•˜๋„๋ก ์ถ”๊ฐ€ํ–ˆ๋‹ค. Observable์€ ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ์ž๋™์œผ๋กœ ํ•ด์ œ(dispose)๊ฐ€ ๋œ๋‹ค.

Observable.interval(0,1,TimeUnit.SECONDS)
  .map(String::valueOf)
  .compose(bindToLifecycle())
  .subscribe(s -> Lob.i("Lifecycle ์ ์šฉํ•œ Observable",s));

2.3.4 RxLifecycle ๋งˆ๋ฌด๋ฆฌ

RxJava2 ์—์„œ๋Š” RxLifecycle์˜ ์ปดํฌ๋„ŒํŠธ ์ด์™ธ์—๋„ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด RxJava์— ์ต์ˆ™ํ•œ ๊ฐœ๋ฐœ์ž๋“ค์€ ์•ˆ๋“œ๋กœ์ด๋“œ์˜ ์ „ํ†ต์ ์ธ ๋ผ์ดํ”„์‚ฌ์ดํด ๊ด€๋ฆฌ ๊ธฐ๋ฒ•๋ณด๋‹ค๋Š” ์ง์ ‘ ๊ด€๋ฆฌํ•˜๊ธฐ ํŽธํ•œ dispose() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ ๊ฒƒ ๋“ฑ์ด ์žˆ๋‹ค.

์–ด๋–ค ๊ฒƒ์ด ์ข‹๋‹ค๊ณ  ์ด์•ผ๊ธฐํ•˜๊ธฐ๋Š” ์–ด๋ ต๊ณ  ๊ฐ๊ฐ ์žฅ,๋‹จ์ ์ด ์žˆ๋‹ค. ์ƒํ™ฉ์— ๋งž๊ฒŒ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž˜ ์„ ํƒํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.



3. RxAndroid ํ™œ์šฉ

3.1 REST API๋ฅผ ํ™œ์šฉํ•œ ๋„คํŠธ์›Œํฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

Retrofit2 + OkHttp ํ™œ์šฉํ•˜๊ธฐ

OkHttp๋Š” ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ‘œ ํด๋ผ์ด์–ธํŠธ ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ ํŽ˜์ด์Šค๋ถ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์œ ๋ช…ํ•˜๋‹ค. SPDY/GZIP ์ง€์› ๋“ฑ ๋„คํŠธ์›Œํ‚น ์Šคํƒ์„ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ , ๋น ๋ฅธ ์‘๋‹ต์†๋„๋ฅผ ๋ณด์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ์žฅ์ ์ด๋‹ค.

Retrofit์€ ์„œ๋ฒ„ ์—ฐ๋™๊ณผ ์‘๋‹ต ์ „์ฒด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค. OkHttp๊ฐ€ ์„œ๋ฒ„์™€์˜ ์—ฐ๋™ ๊ด€๋ จ ๊ธฐ๋Šฅ๋งŒ ์ œ๊ณตํ•œ๋‹ค๋ฉด ์‘๋‹ต๊นŒ์ง€ ๊ด€๋ฆฌํ•ด์ค€๋‹ค๋Š” ๋ฉด์—์„œ ํŽธ๋ฆฌํ•˜๋‹ค. Retofit 1.x ๋ฒ„์ „์—์„œ๋Š” OkHttp, HttpClient ๋“ฑ ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๋ฅผ ์„ ํƒํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ, 2.x ๋ฒ„์ „์—์„œ๋Š” HttpClient๋Š” ๋” ์ด์ƒ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ณ  OkHttp์— ์˜์กดํ•˜๋„๋ก ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค.

RxAndroid์—์„œ Retrofit2 + OkHttp ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉํ•˜๊ธฐ

Retrofit์˜ ์žฅ์  ์ค‘ ํ•˜๋‚˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์Šคํ”„๋ง์ฒ˜๋Ÿผ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ API๋ฅผ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด @Header๋ฅผ ์ด์šฉํ•˜์—ฌ ํ—ค๋”๋ฅผ ์„ค์ •ํ•˜๊ณ , @GET์ด๋‚˜ @POST ๋“ฑ์œผ๋กœ ์‚ฌ์šฉํ•  HTTP ๋ฉ”์†Œ๋“œ๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋‹ค.

Retrofit์€ RxJava๋ฅผ ์ •์‹์œผ๋กœ ์ง€์›ํ•˜๋ฏ€๋กœ Observable์„ API ๋ฆฌํ„ด๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ ์™ธ์— Call๊ณผ Future ์ธํ„ฐํŽ˜์ด์Šค๋„ ์ง€์›ํ•œ๋‹ค.

Java๋ฅผ ์ด์šฉํ•œ ๊ธฐ์กด ์ฝ”๋“œ

public interface RestAPI {
    @GET(APIUrl.QUIZZES_URL)
    Call<JsonObject> quizzes();

    @FormUrlEncoded
    @POST(APIUrl.LOGIN_URL)
    Call<JsonObject> login(@Field("kakaoID") long kakaoId);

    @FormUrlEncoded
    @POST(APIUrl.UPDATE_EXP)
    Call<JsonObject> updateExp(@Field("exp") int exp, @Field("id") long id);
}

RxJava๋ฅผ ์ ์šฉํ•œ ์ฝ”๋“œ

๋ฐ˜ํ™˜๊ฐ’์ด Observable์ธ ๊ฒƒ์ด ์ฐจ์ด์ ์ด๋‹ค.

public interface RestAPI {
    @GET(APIUrl.QUIZZES_URL)
    Observable<JsonObject> quizzes();

    @FormUrlEncoded
    @POST(APIUrl.LOGIN_URL)
    Observable<JsonObject> login(@Field("kakaoID") long kakaoId);

    @FormUrlEncoded
    @POST(APIUrl.UPDATE_EXP)
    Observable<JsonObject> updateExp(@Field("exp") int exp, @Field("id") long id);
}

Rxjava์™€ Retrofit2์„ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ์–ด๋Žํ„ฐ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€ํ–ˆ๋‹ค. ์ •ํ™•ํžˆ๋Š” RxJava2CallAdapterFactory๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด retrofit instance๋ฅผ ๋นŒ๋“œ ํ•  ๋•Œ RxJava2CallAdapterFactory๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ Observable์ด๋‚˜ Single๊ฐ™์€ ํƒ€์ž…์„ ๋ฑ‰์„ ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://google.com/")
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
  	.addConverterFactory(GsonConverterFactory.create())
    .build();
// RxJava + Retofit + OkHttp
private void startRx(){
  GithubServiceApi service = RestfulAdapter.getInstance().getServiceApi();
  Observable<List<Contributor>> observable = 
    service.getObContributors(name,repo);
  
  mCompositeDisposable.add(
    observable.subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    //Observable์„ ๊ตฌ๋…
    .subscribeWith(new DisposableObserver<List<Contributor>>(){
      @Override
      public void onNext(List<Contributor> contributors){
        for(Contributor c : contributors){
          log(c.toString());
        }
      }
    })
    
  )
}

startRx() ๋ฉ”์†Œ๋“œ๋Š” RestfulAdapter ํด๋ž˜์Šค์˜ getServiceApi() ๋ฉ”์„œ๋“œ ์•ˆ retrofit ๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•ด ์ƒ์„ฑ๋œ API ํ”„๋ฝ์‹œ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. owner์™€ repo์˜ ๊ฐ’์„ ์ „๋‹ฌํ•˜๋ฉด observable ๋ณ€์ˆ˜์— ์ €์žฅ๋œ Observable์„ ๋ฆฌํ„ดํ•œ๋‹ค. ์ƒ์„ฑ๋œ Observable์— ๊ตฌ๋…์ž๋ฅผ ์„ค์ •ํ•˜๋ฉด getServiceApi() ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ github.com์—์„œ ์ •๋ณด๋ฅผ ์–ป์–ด์˜จ๋‹ค.

๊ฒฐ๊ณผ๋Š” ๊ตฌ๋…์ž๊ฐ€ ์ˆ˜์‹ ํ•˜๊ฒŒ ๋˜๊ณ  GSON์—์„œ Contributor ํด๋ž˜์Šค์˜ ๊ตฌ์กฐ์— ๋งž๊ฒŒ ๋””์ฝ”๋”ฉํ•œ ๋‹ค์Œ UI์Šค๋ ˆ๋“œ๋ฅผ ์ด์šฉํ•ด ํ™”๋ฉด์— ์—…๋ฐ์ดํŠธํ•œ๋‹ค.

์ƒ์„ฑ๋œ Disposable ๊ฐ์ฒด๋ฅผ CompositeDisposable์—์„œ ๊ด€๋ฆฌํ•˜๋„๋ก CompositeDisposable.add() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ถ”๊ฐ€ํ•œ๋‹ค. CompositeDisposable ์„ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ Disposable ๊ฐ์ฒด๋ฅผ ํ•œ๋ฒˆ์— ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

protected void onDestroy() {
    super.onDestroy();

    mCompositeDisposable.clear();
}

[๊ธฐ์กด Java ์ฝ”๋“œ]

// Retofit + OkHttp
Call<JsonObject> call = restAPI.updateExp(30,pref.getLong("userID", 0));
call.enqueue(new Callback<JsonObject>() {
  @Override
  public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
    if (response.code() == 200) {
      Log.d("response----", response.body().toString());
      
    }
  }

  @Override
  public void onFailure(Call<JsonObject> call, Throwable t) {
    Log.d("ERROR! onFailure!", t.toString());
  }
});

์œ„์™€ ๋™์ผํ•˜๋‹ค. ํ•˜์ง€๋งŒ getXXX ๋ฉ”์†Œ๋“œ์˜ ์‹คํ–‰์„ ์œ„ํ•ด์„œ๋Š” retrofit์—์„œ ์ œ๊ณตํ•˜๋Š” Call ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. Call ์ธํ„ฐํŽ˜์ด์Šค์˜ enqueue() ๋ฉ”์†Œ๋“œ์— ์ฝœ๋ฐฑ์„ ๋“ฑ๋กํ•˜๋ฉด GSON์—์„œ ๋””์ฝ”๋”ฉํ•œ ๊ฒฐ๊ณผ๋ฅผ ํ™”๋ฉด์— ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋‹ค.



๋งˆ์น˜๋ฉฐ

Reference

[๋„์„œ] RxJava ํ”„๋กœ๊ทธ๋ž˜๋ฐ (์œ ๋™ํ•œ, ๋ฐ•์ •์ค€ ์ง€์Œ)