์์ฑ์ผ: 2018.03.07
์ด ๊ธ์ ์๋ฌธ์ ๋ฒ์ญํ ๊ธ์ ๋๋ค.
RxJava for 100% beginners(part 1)
์์ฆ์ ๋ง์ Android ๊ฐ๋ฐ์๋ค์ด “Reactive Programming/RxJava”์ ์กด์ฌ๋ฅผ ์ ์๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ต๊ทผ Android Weekly์๋ ๋งค ์ฃผ RxJava์ ๊ด๋ จ๋ ๋ธ๋ก๊ทธ ํฌ์คํธ๊ฐ ํญ์ ์๊ธฐ๋ ํ์ต๋๋ค.
ํ์ง๋ง, RxJava์ ๋ฌธ๋ฒ์ ์ฌ์ฉ๋ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๋ํด ์ ๋ชจ๋ฅด๋ ์ด๋ณด์์๊ฒ๋ ์กฐ๊ธ ์ด๋ ค์ธ ์ ์์ต๋๋ค. Scala์์๋, RxJava์ map(), filter(), flatmap() ๋ฑ๊ณผ ์ ์ฌํ ์คํผ๋ ์ดํฐ๋ค์ด ์์ต๋๋ค. ๋ง์ฝ ์ด์ ์ Scalar๋ (RxJava๊ฐ ๊ฐ๋
๊ณผ ๋ฌธ๋ฒ์ ์ฐจ์ฉํ) ๋ค๋ฅธ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ฅผ ์ฌ์ฉํด๋ดค๋ค๋ฉด, ์์ ์จ๋ณด์ง ์์ ์ฌ๋๋ณด๋ค๋ ๋์ ์๋ ์์ต๋๋ค. ์ด ์๋ฆฌ์ฆ์์๋, ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์์ ๋ชจ๋ฅด๋ ๋ถ๋ค์ ์ํด ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๊ธฐ๋ณธ๋ถํฐ ๋ค๋ฃจ๋ ค๊ณ ํฉ๋๋ค. ๋คํํ Java8๋ถํฐ Stream API๊ฐ ์ถ๊ฐ๋๊ณ , “Stream” ํด๋์ค๋ RxJava์ “Observable”๊ณผ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. ๊ทธ๋์ RxJava์ Observable์ ์ดํดํ๊ธฐ ์ํด Java8์ Stream API์ ๋ช๋ช ์์๋ฅผ ํจ๊ป ์ดํด๋ณผ ๊ฒ์
๋๋ค.
๊ทธ๋ผ ์ด์ ์์ํ๊ฒ ์ต๋๋ค!
์ด๋ณด์๋ถ๋ค์ ์ํด, ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ 2๊ฐ์ง ์ฃผ์ ์ด์ ๋ถํฐ ๋ณด๋ฉด:
- ํจ์๋ ๋ค๋ฅธ ํจ์์ ํ๋ผ๋ฏธํฐ๊ฐ ๋ ์ ์๊ณ , ์ด๊ฒ์ “first-class object”๋ผ๊ณ ํฉ๋๋ค.
- ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ operation์ ์ํ์์์ “ํจ์”์ฒ๋ผ ๋ค๋ฃน๋๋ค. -> ์ฐ๋ฆฌ๋ ๋ง์ง๋ง ํจ์์ ๊ฒฐ๊ณผ๋ ๋ฐํ๊ฐ์๋ง ์ ๊ฒฝ์ฐ๋ฉด ๋ฉ๋๋ค. (์ํ ๋ณํ๋ ๊ฐ์ฒด์ ๋ณ๊ฒฝ์ ๊ฑฑ์ ํ ํ์๊ฐ ์์ต๋๋ค.)
RxJava์ Java8 Stream API๋ ๋๋ค ํํ์์ ์ง์ํฉ๋๋ค. ๋๋ค ํํ์์ ์์ ์ฒซ๋ฒ์งธ ์ฅ์ ์ ์ ๋ํ๋
๋๋ค. ์์์ ํจ๊ป ๋ณด๊ฒ ์ต๋๋ค:
interface NewAction{
void call();
}
public static void execute(NewAction action){
action.call();
}
public static void main(String[] args) {
execute( new NewAction() {
@Override
public void call() {
// TODO Auto-generated method stub
System.out.println("action start");
}
} );
execute(()->System.out.println("action start"));
}
line 11 execute( new NewAction(... ๊ณผ line 21 execute(()->... ์ ์ฐจ์ด์ ์ ๋ณด๋ฉด, ๋ ๋ค “action start”๋ฅผ ์ถ๋ ฅํ์ง๋ง, line 21์ด ํจ์ฌ ์งง์ต๋๋ค. ์ด์ “NewAction” ์ธํฐํ์ด์ค์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ “call” ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ ํ์๊ฐ ์์ต๋๋ค. ๋ฉ์๋ ๋ฐ๋์ ์ฝ๋๋ฅผ ์์ฑํ๊ณ execute()๋ก ์ ๋ฌ๋ง ํ๋ฉด ๋ฉ๋๋ค. That’s not magic!
Java 8์ ์ฌ์ฉํ๋ฉด, ๋๋ค ํํ์์ ๋ง์๊ป ์ธ ์ ์์ต๋๋ค. ํ๋์ ๋ฉ์๋๋ง ํฌํจํ๋ ์ธํฐํ์ด์ค๊ฐ ํ์ํ ๋ ์ฝ๋์์ ์ธํฐํ์ด์ค ์ธ์คํด์ค๋ฅผ ์ง์ ์์ฑํ์ง ์๊ณ , ๋ฉ์๋ ๋ฐ๋๋ฅผ ์ํ๋ ๊ณณ์ ์์ฑํ๋ฉด ๋ฉ๋๋ค.
๊ทธ๋ฌ๋, ์ฌ๊ธฐ์ ํจ์๊ฐ ์ ๋ง ํ๋ผ๋ฏธํฐ์ฒ๋ผ ์ฌ์ฉ๋๋ ๊ฑด ์๋๋๋ค. ๋จ์ง ์ ์ ์ฝ๋๊ฐ ๊ฐ๋ฅํ๊ฒ ํด์ฃผ๊ณ , ํจ์๋ฅผ ํ๋ผ๋ฏธํฐ์ฒ๋ผ ์ ๋ฌํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๊ฒ ํ๋ ์ปดํ์ผ๋ฌ์ ๊ธฐ๋ฅ์
๋๋ค.
์, ๊ทธ๋ผ 2๋ฒ ์ฅ์ ์ ์์๋ฅผ ์๋์์ ์ดํด๋ณด๊ฒ ์ต๋๋ค!
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<Integer>();
arrayList.stream()
.map(integer -> integer + 1)
.filter(integer -> integer < 10)
.limit(10);
}
์ ์์ ์์, ArrayList๋ฅผ Stream(Java์ InputStream์ด๋ OutStream ๊ฐ์ ๊ฐ๋
์ด ์๋๋๋ค)์ผ๋ก ๋ณํํ๊ณ , ๋ค๋ฅธ ์ฐ์ฐ์์ ์ ์ฉํ์ฌ Stream์ ์์ ํ์ต๋๋ค. ๋จผ์ Stream(Integer ๊ฐ์ฒด์ ์คํธ๋ฆผ)์ ๋ชจ๋ ์์์ 1์ฉ ๋ํ๋๋ก map์ ์ ์ฉํ๊ณ , 10๋ณด๋ค ์์ ์ ์๋ก ํํฐ๋งํ ํ, ์์์ 10๊ฐ์ ์์๋ง ์คํธ๋ฆผ์์ ๊ฐ์ ธ์์ต๋๋ค. ์ฐ์ฐ์๋ฅผ ์ ์ฉํ ๋๋ง๋ค ์๋ก์ด ์คํธ๋ฆผ์ด “์์ฑ”๋๋ฉฐ, ๊ทธ๋์ ์ฐ์ฐ์๋ค์ ์ฐ์๋ก ์ ์ฉํ ์ ์์ต๋๋ค.
๊ทธ๋ฐ๋ฐ ์ ๊น.. ์ด๋ฐ ํน์ดํ ๊ตฌ์กฐ๋ฅผ ์จ์ ์ข์ ์ ์ ๋ญ๊น์?
์์์ ์ด๋ฏธ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ๋ํด ์ธ๊ธ์ ํ์๋๋ฐ, “์ํ”๋ฅผ ๊ฐ์ง ์๊ณ ํจ์ ์คํ์ ๊ฒฐ๊ณผ์๋ง ์ง์คํ ์ ์๋๋ก ํ๋ ๊ฒ์ด ๋ชฉ์ ์
๋๋ค.
์๋ฅผ ๋ค์ด ์๋์ ๊ฐ์ ํจ์ ์คํ ์์๊ฐ ์๋ค๊ณ ๊ฐ์ ํ๋ฉด:
funcA() -> funB() -> funcC();
์ด ๊ฒฝ์ฐ, funC()๋ funcB()์ ๊ฒฐ๊ณผ๋ง ๋ค๋ฃจ๊ณ , funcA()์ ๊ฒฐ๊ณผ๋ ์ฌ์ฉํ์ง ์์ ๊ฒ์
๋๋ค. ์ด๊ฒ์ด ๊ฐ์ฅ ์ด์์ ์ธ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์์์ ์๋๋ฆฌ์ค์
๋๋ค.
๋๋ถ๋ถ ์ฌ๋๋ค์ ์ด๋ฐ์์ผ๋ก ๊ตฌํํ ๊ฒ์
๋๋ค:
private boolean flag;
void A(){
flag = true;
//do something
B();
}
void B(){
C();
}
void C(){
if(flag){
//do something
}
}
์ด ์์ ์์, C()์ ์คํ์ ์ปจํธ๋กคํ๊ธฐ ์ํด ์ ์ญ๋ณ์๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ํ์ง๋ง ๋ณ์๋ ๋ณํ ์ ์๊ณ A() ์์์๋ ๋ฐ๋ ์ ์์ต๋๋ค. ๊ทธ๋์ ํจ์ ์คํ ์์๊ฐ A()->B()->C()๋ผ๊ณ ํด๋, C()๋ B()์ ๋ํด ์์ํ ์ํ๊ฐ ์๋๋ฉฐ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๋ฃฐ์๋ ์ด๊ธ๋ฉ๋๋ค.
์ฝ๋๋ฅผ ์ด์ง ๋ฐ๊ฟ๋ณผ๊น์.
void A(){
boolean flag = true;
//do something
B(flag);
}
void B(boolean flag){
C(flag);
}
void C(boolean flag){
if(flag){
//do something
}
}
ํจ์ฌ ๋ซ๋ค์! B()์ C()๋ ๋์ด์ ์ ์ญ๋ณ์์ ์ํฅ์ ๋ฐ์ง ์๊ณ , B()์ C()์ ๊ฒฐ๊ณผ๋ ์์ํ๊ฒ ๊ฐ๊ฐ์ ํ๋ผ๋ฏธํฐ์ ์ํด์ ๊ฒฐ์ ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ “RxJava”์ค๋ฝ๊ฒ ๋ฐ๊พผ๋ค๋ฉด
public static void main(String[] args) {
new Exe(true)
.A()
.B()
.C();
}
static class Exe {
boolean flag;
public Exe(boolean flag){
this.flag = flag;
//do something
}
Exe A(){
boolean flag = true;
//do something
return new Exe(flag);
}
Exe B(){
return new Exe(flag);
}
Exe C(){
if(flag){
//do something
}
return new Exe(flag);
}
}
์ ์ฝ๋๋ ์ฐ๋ฆฌ๊ฐ ์ด๋ป๊ฒ ๋ functionalํ๊ฒ ๋ง๋ค ์ ์๋์ง ๋ณด์ฌ์ค๋๋ค!
๊ทธ๋ฌ๋ ์ฌ๊ธฐ์ ์๋ฌธ์ ์ -> ์ฌ์ ํ Exe ํด๋์ค์ boolean ํ๋๊ทธ๊ฐ ์๋ค๋ ๊ฒ์
๋๋ค! ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ์์น์ ์ด๊ธ๋์ง ์์๊น์?
์, ๊ทธ๋ ์ง ์์ต๋๋ค. ๋ฉ์๋ ์ฒด์ธ์ ์คํ์ ํต์ ํ๊ธฐ ์ํด ๋ณํ ์ ์๋ ๋ณ์๋ฅผ ์ํ์ง ์๋๋ค๋ฉด ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ์์น์ ์ด๊ธ๋๋ค๋ ๊ฒ์ ํญ์ ๊ธฐ์ตํ์ธ์. ํ์ง๋ง ์ด ๋ง์ด ์ ์ญ๋ณ์๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ ์๋ฏธ๋ ์๋๋๋ค. ์์ ์ฝ๋์์, A(), B(), C()๋ฅผ ์คํํ ๋๋ง๋ค Exeํด๋์ค์ ์๋ก์ด ์ธ์คํด์ค๋ฅผ ๋ฐํํ์ฌ ๊ฐ์ Exe ์ธ์คํด์ค๋ฅผ ๊ณต์ ํ์ง ์์ต๋๋ค. ์ด ๋ง์ ๋ฐ๋ก ์ด์ ์ Exe ์ธ์คํด์ค๋ง ํ์ฌ ๋ฉ์๋์ ์คํ์ ๊ด์ฌํ๋ค๋ ์๋ฏธ์
๋๋ค.
๊ทธ๋ผ ์ด์ Java8์ Stream API๋ฅผ ๋ค์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. map(), filter(), limit() ๊ฐ์ ์ฐ์ฐ์๊ฐ ์๋ก์ด “Stream”์ ์์ฑํด ๋ค์ ์ฐ์ฐ์์ ๋๊ฒจ์ค๋๋ค. ์ด์ ์ฐ์ฐ์์ ์ํด ๋ง๋ค์ด์ง ์คํธ๋ฆผ์ ๋ณ๊ฒฝํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<Integer>();
arrayList.stream()
.map(integer -> integer + 1)
//at this point, stream has already been modified by adding 1 to each element
.filter(integer -> integer < 10)
//at this point, stream has already been modified by filtering out those numbers less than 10
.limit(10);
}
์ฌ๊ธฐ๊น์ง๊ฐ part1 ๋ด์ฉ์ ๋๋ค. ๋ค์ ํฌ์คํธ์์๋ RxJava์ ์ฐ์ฐ์์ API๋ฅผ ๋ค๋ฃจ๊ฒ ์ต๋๋ค.
'๊ฐ๋ฐ > Android' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android] Kotlin Extension Function์ ์ฌ์ฉํ์ฌ ๋๋ธ ํด๋ฆญ ๋ฐฉ์งํ๊ธฐ (0) | 2021.04.08 |
---|---|
[Android] Jetpack - LiveData (0) | 2021.04.08 |
[Android] ๋ ์ด์์ ๊ณ์ธต ์ฑ๋ฅ ์ต์ ํ(Optimizing Layout Hierarchies) (0) | 2021.04.08 |
[Android] Bitmap์ ์์ ์ ํ๊ธฐ (0) | 2021.04.08 |
[Android] Live Data (0) | 2021.04.08 |