본문 바로가기
Rx

안드로이드의 RxJava 활용 - 10( REST API를 활용한 네트워크,Volley)

by 봄석 2018. 12. 30.

본 내용은 필자가 학습한 내용을 정리하는 내용입니다.

대부분 의 내용이 아래 책의 내용이므로 원서를 구매해서 직접보시는걸 추천드립니다!

RxJava 프로그래밍 리액티브 프로그래밍 기초부터 RxAndroid까지 한 번에

유동환 , 박정준 지음 | 한빛미디어 | 2017년 09월 04일 출간

http://www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788968488658&orderClick=LAV&Kc=


저자님의 블로그

https://brunch.co.kr/@yudong#info




REST API를 활용한 네트워크 프로그래밍

REST네트워크 아키텍처 원리의 모음으로 ' 네트워크 아키텍처 원리' 라는 자원을 정의하고 

자원에 대한 주소를 지정하는 방법 전반을 말합니다. 웹상의 자료를 HTTP위에서 SOAP나 쿠키를 통한 세션 트랙킹 같은 별도의 전송 계층 없이 전송하는 아주 간단한 인터페이스입니다.


간단하게 설명하면 아래와 같습니다.

1) HTTP를 사용한 웹서비스 입니다.

2) 모든 자원은 고유 주소 (URL) 로 식별합니다.

3) HTTP 메소드(GET, POST, PUT, DELETE)를 사용합니다.

4) JSON, XML등을 사용합니다.


이러한 사양에 따라 구현된 서비스를 RESTful 웹서비스라고 합니다. 네이버, 구글, 아마존 등도 RESTful API를 이용한 웹 서비스를 제공합니다. 


이번에는 안드로이드에서 사용하는 대표적인 RESTful 라이브러리와 여기에 RxJava를 적용하여 사용하는 방법을 알아보겠습니다.


Volley 라이브러리 활용

Volley는 구글 IO 에서 2013 공개한 안드로이드용 라이브러리입니다. 다른 안드로이드용 HTTP 클라이언트 라이브러리가 제공하는 기능을 제공하면서도 용량이 작고 빠른 실행속도를 자랑합니다. 구글은 안드로이드에 아파치 HttpClient와 HttpURLConnection 클래스로 HTTP 클라이언트 라이브러리를 제공하지만 Volley와 같은 라이브러리 사용을 권장합니다.

 

아파치 HttpClient나 HttpURLConnection 클래스를 사용해본 개발자라면 스레딩, 동기화, 병렬 처리를 위해 많은 시간을 투자해야 한다는 것을 알 것입니다. Volley는 이런 처리를 쉽게 할수 있는 인터페이스를 제공하여 개발자가 비즈니스 로직을 만드는 데 집중할 수 있도록 합니다.


Volley의 사용법

1) RequestQueue 생성

2) Request Object 생성   

3) Request Object를 RequestQueue 에 추가 .

4) 설정한 Callback으로 응답 수신.


다음은 Volley 라이브러리를 이용하여 http://time.jsontest.com/의 시간 정보를 얻는 코드를 작성해 보겠습니다.


RequestQueue 생성하기 volley/LocalVolley.java

public class LocalVolley {
    private static RequestQueue sRequestQueue;
 
    private LocalVolley() {
 
    }
 
    public static void init(Context context) {
        sRequestQueue = Volley.newRequestQueue(context);
    }
 
    public static RequestQueue getsRequestQueue() {
        if (sRequestQueue != null) {
            return sRequestQueue;
        }else
            throw new IllegalStateException("Not Inited");
    }

}



LocalVooely 클래스는 init() 메소드가 호출되면 Context를 이용하여 RequestQueue를 생성합니다. 생성된 RequestQueue는 getRequestQueue() 메소를 이용하여 가져올 수 있습니다.


LocalVolley 초기화하기 RxAndroid.java



RxAndroid는 Application 클래스를 상속받고 있습니다.  애플리케이션이 시작하면 해당 클래스의 onCreate() 메소드가 최우선으로 호출되고 단 한번만 실행됩니다.


애플리케이션 실행을 시작하면서 LocalVolley 클래스의 init() 메소드가 호출되고 Volley의 RequestQueue를 사용할 수 있게 초기화 합니다. 싱글턴(Singleton) 방식으로 초기화하여 사용할 수도 있지만 Context를 가지고 있어야하는 부담이 있어  애플리케이션이 생성되는 시점에 Queue를 생성합니다. 싱글턴과 동일한 효과가 있습니다.

싱글턴이란 무엇인가 참고 ->https://jeong-pro.tistory.com/86


RequestObject 생성, RequestQueue에 추가 , 콜백 등록하기

private RequestFuture<JSONObject> getFuture() {
        RequestFuture<JSONObject> future = RequestFuture.newFuture();
        JsonObjectRequest req = new JsonObjectRequest(URL, null, future, future);
        return future;
    }
    private JSONObject getData() throws ExecutionException, InterruptedException {
        return getFuture().get();
    }


getFuture() 메소드는 생성한 JsonObjectRequest객체를 RequestQueue에 추가합니다.

JsonObjectRequest() 메소드의 명세는 다음과 같습니다.

JsonObjectRequest(String url, JSONObject jsonRequest, 

    Listener<JSONObject> listener, ErrorListener errorListener)


위 코드에서는 에러와 결과 리스너에 동일한 RequestFuture 콜백을 설정하여 에러와 결과 모두를 RequestFuture 객체로 받일수 있게합니다. 여기서 관심을 가져야 하는 부분은 Volley 라이브러리의 콜백을 Future 객체로 대체한 것입니다.


Future<T>는 자바에서 사용하는 비동기 계산 결과를 얻는 객체입니다. 지연완료(pending completion) 객체라고도 합니다. 자바 8 이후로는 Observable과 비슷한 여러 개의 요청에 대한 비동기 처리를 할 수 있는 CompletableFuture<T> 도 제공합니다.


Observable에서는 다양한 비동기 함수를 제공합니다. 여기서는 defer(), fromCallable(), fromFuture() 함수를 이용하여 Volley 의 RequestFuture 객체를 처리합니다.


시간 정보 얻기 1

private Observable<JSONObject> getObservable() {
        return Observable.defer(() -> {
            try {
                return Observable.just(getData());
            } catch (InterruptedException e) {
                log("error : " + e.getMessage());
                return Observable.error(e);
            } catch (ExecutionException e) {
                log("error : " + e.getCause());
                return Observable.error(e.getCause());
            }
        });
    }



defer() 는 대표적인 비동기 함수로 supplier( () -> T)를 매개변수로 사용하고 T의 데이터 타입은 

Callable<? extneds Observablesource<? extends T>> 입니다. Observable.just()를 사용하여 새로운 Observable을 생성하는 이유는 내부적으로 예외처리를 하지 못하기 때문입니다.

try-catch 문을 이용하여 명시적으로 에러를 처리해야 합니다.



시간 정보 얻기 1 동작순서 

->버튼클릭 ->post() 에서 getObservable 함수 호출->Observable.defer() )응답을 받을때까지 지연하기위해) 응답을 받으면 Observable.just()로 발행하기위해 getData() 함수호출->getData() 함수에서는 getFuture().get()호출-> 리퀘스트큐에 URL,future를 추가한 후(이떄 요청보내짐) future  getData() 로리턴-> getData()는 다시 getObservable()의 just()함수로 리턴받음-> 리턴받은값 post()함수로 전달 post함수는 getObserver() 함수를 호출해 응답내용을 DisposableObserver의 onNext로 발행 ,동시에 mCompositeDisposable에 추가하면서 Schdedulers.io()로 작업스레드에서 작업하고, observeOn(AndroidSchedulers.mainThread()로 작업한내용 전달받아 UI 업데이트





시간 정보 얻기 2

 private Observable<JSONObject> getObservableFromCallable() {
        return Observable.fromCallable(this::getData);
    }



fromCallable()함수는 Callable<? extends T> supplier 를 매개변수로 사용합니다.

defer() 함수와는 다르게 어떤 데이터 타입도 사용할 수 있습니다. fromCallable() 함수를 이용하기 위해서는 Future 객체를 직접 전달하지 않고 Future.get() 을 전달합니다.


시간 정보 얻기 2 동작순서 

->버튼 클릭-> post()에서 getObservableFromCallble() 호출-> getData() 호출-> getFuture()호출-> Future 객체를 만들어  리퀘스트큐에 값 (URL, future등 )넣어줌 (이때 요청보내짐)

->getData()로 future값 getObservableFromCallable()로 리턴 -> fromCallable()함수를 통해 비동기 처리하고, 리턴받을 값이 오게되면  그값을 다시 post()로보내줌-> post함수는 getObserver() 함수를 호출해 응답내용을 DisposableObserver의 onNext로 발행 ,동시에 mCompositeDisposable에 추가하면서 Schdedulers.io()로 작업스레드에서 작업하고, observeOn(AndroidSchedulers.mainThread()로 작업한내용 전달받아 UI 업데이트



fromCallable() 함수의 마블다이어그램


이 마블 다이어그램을 적용해 변경한 결과는 아래와같습니다.


시간 정보 얻기 3

private Observable<JSONObject> getObservableFromFuture() {
        return Observable.fromFuture(getFuture());
    }




RxJava 2.x의 fromFuture() 함수는 Future<? extends T> future를 매개변수로 사용합니다. 

아래 마블다이어그램처럼 Observable 내부에서 get() 메소드를 요청하고 결과를 전달받아 Future 객체 자체를 내부에서 바로 처리합니다.



시간 정보 얻기 3 동작순서

->버튼클릭->post() 에서 getObservableFromFuture() 호출 ->getFuture() 호출

-> Future를 생성하고 , 리퀘스트큐에 URL,Future 등을 넣음  그리고 future를 getObservableFromFuture()로 리턴-> getObservableFromFuture() 함수는 fromFuture()함수로 

요청한값을 비동기처리(응답올 떄까지 블럭) 한후 그값을 post()로 리턴->post함수는 getObserver() 함수를 호출해 응답내용을 DisposableObserver의 onNext로 발행 ,동시에 mCompositeDisposable에 추가하면서 Schdedulers.io()로 작업스레드에서 작업하고, observeOn(AndroidSchedulers.mainThread()로 작업한내용 전달받아 UI 업데이트




CompositeDisposable과 DisposableObserver

구독 시작 시 호출되는 onSubscribe()에서 disposable CompositeDisposable에 담아 놓으면 구독을 취소하고 싶을 때 이용할 수 있습니다. (onDestroy() 등에서  CompositeDisposable.clear(); 합니다)

disposable은 일회용으로 생각하면 됩니다 쓰난후 Dispose합니다



댓글