투케이2K

669. (Android/Java) [Rx] repeatWhen 사용해 http 폴링 방식 요청 수행 실시 - http polling request 본문

Android

669. (Android/Java) [Rx] repeatWhen 사용해 http 폴링 방식 요청 수행 실시 - http polling request

투케이2K 2023. 10. 17. 07:58

[개발 환경 설정]

개발 툴 : AndroidStudio

 

[소스 코드]

        // ----------------------------------------------------------------------------------------------------------------
        // [HTTP 폴링 요청 부분]
        // ----------------------------------------------------------------------------------------------------------------
        try {

            /**
             * // -----------------------------------------
             * [요약 설명]
             * // -----------------------------------------
             * 1. 개발 환경 : 안드로이드 스튜디오
             * // -----------------------------------------
             * 2. Rx 관련 라이브러리 설치 (build.gradle) :
             *
             * implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
             * implementation 'io.reactivex.rxjava3:rxkotlin:3.0.1'
             * implementation 'io.reactivex.rxjava3:rxjava:3.0.7'
             * // -----------------------------------------
             * 3. Scheduler (스케줄러) 기본 개념
             *
             * Scheduler 는 반응형 프로그래밍에서 동시성을 관리하며, 스레드 관리를 제어하기 위한 subscribeOn , observeOn 메소드 가 있습니다
             * Scheduler 관련 용어 설명 :
             *   - AndroidSchedulers.mainThread() : 안드로이드의 UI 스레드에서 동작
             *   - Schedulers.io() : 비동기 처리를 위해 사용하는 스케줄러 (API 호출 등 네트워크를 사용한 호출)
             *   - Schedulers.computation() : 이벤트 그룹에서 간단한 연산이나 콜백 처리를 위해 사용 (스레드 풀이 순환하면서 실행됨)
             *   - Schedulers.from(executor) : 특정 executor를 스케줄러로 사용
             *   - Schedulers.newThread() : 새로운 스레드를 만드는 스케줄러
             *   - Schedulers.trampoline() : 큐에 있는 일이 끝나면 이어서 현재 스레드에서 수행
             *   - HandlerScheduler.from(handler) : 특정 핸들러 handler 에 의존하여 동작
             * // -----------------------------------------
             * */


            // [http 요청 폴링 카운트 지정]
            final int[] count = {3};


            // [URL 주소 선언]
            String url = "https://jsonplaceholder.typicode.com/posts";


            // [파라미터 생성]
            Map <String, Object> params = new HashMap<>();
            params.put("userId", 1);
            params.put("id", 1);


            // [http 요청 수행]
            N_AsyncHttp.requestGetQueryStringHttp(A_Intro.this, "http 요청", url, null, params) // [http 요청]

                    // ------------------------------------------------------------
                    .repeatWhen(obj-> obj.delay(3000L, TimeUnit.MILLISECONDS)) // TODO [3000 == 3초 마다 폴링]
                    // ------------------------------------------------------------
                    .retry((retryCnt, e)->{ // TODO [retry : onError 발생 시 재요청 시도 : 지정 횟수 동안 재호출]
                        S_Log._E_("http :: retry", new String[]{ String.valueOf(retryCnt) });
                        return retryCnt < 3 ? true : false;
                    })
                    // ------------------------------------------------------------
                    .subscribeOn(AndroidSchedulers.mainThread()) // [Observable (생성자) 로직을 IO 스레드에서 실행 : 백그라운드]
                    .observeOn(Schedulers.io()) // [Observer (관찰자) 로직을 메인 스레드에서 실행]
                    .subscribe(new DisposableObserver<String>() { // TODO [DisposableObserver : dispose : 아이템 발행을 중단 지정 위함]
                        @Override
                        public void onNext(@NonNull String value) {
                            S_Log._W_("http :: onNext", new String[]{ "COUNT :: " + String.valueOf(count[0]), "VALUE :: " + String.valueOf(value) });

                            // [카운트 감소]
                            count[0] -= 1;

                            // [폴링 카운트 횟수 체크]
                            if (count[0] <= 0){
                                S_Log._E_("http :: onNext", new String[]{ "Polling Count End" });

                                dispose(); // TODO [아이템 발행을 중단 : 완료 처리]
                            }
                        }

                        @Override
                        public void onError(@NonNull Throwable e) {
                            S_Log._E_("http :: onError", new String[]{ String.valueOf(e.getMessage()) });
                        }

                        @Override
                        public void onComplete() {
                        }
                    });

        }
        catch (Exception e){
            e.printStackTrace();
        }










    // ----------------------------------------------------------------------------------------------------------------

    // [Observable :: http 통신 수행 부분]
    // ----------------------------------------------------------------------------------------------------------------
    public static Observable<String> requestGetQueryStringHttp(Context mContext, String tag, String url, Map header, Map params){        

        // [로직 처리 실시]
        return Observable.create(subscriber -> {

            try {

                // ------------------------------------------------------
                // TODO [URL 변수 선언 실시]
                // ------------------------------------------------------
                String urlData = String.valueOf(url);
                // ------------------------------------------------------



                // ------------------------------------------------------
                // TODO [url 에 파라미터 추가 실시]
                // ------------------------------------------------------
                if (C_Util.mapNotNull(params) == true) { // [파라미터가 있는 경우]

                    if (urlData.endsWith("?") == false){
                        urlData = urlData + "?";
                    }

                    urlData = urlData + C_Util.mapToUrlEncodeQueryString(params);
                }
                // ------------------------------------------------------



                // ------------------------------------------------------
                // TODO [OK HTTP 객체 선언 실시]
                // ------------------------------------------------------
                //OkHttpClient client = new OkHttpClient();
                OkHttpClient client = new OkHttpClient.Builder()
                        .connectTimeout(TIME_OUT_SECOND, TimeUnit.SECONDS) // [커넥션 제한 시간]
                        //.readTimeout(10, TimeUnit.SECONDS)
                        //.writeTimeout(10, TimeUnit.SECONDS)
                        .retryOnConnectionFailure(false)
                        .build();

                Request.Builder request = new Request.Builder();
                request.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8;"); //TODO [헤더]
                request.addHeader("Cache-Control", "no-cache"); //TODO [헤더]

                if (C_Util.mapNotNull(header) == true){
                    Set set = header.keySet();
                    Iterator iterator = set.iterator();
                    while(iterator.hasNext()){
                        String key = (String) iterator.next();
                        request.addHeader(key, String.valueOf(header.get(key))); //TODO [헤더 추가]
                    }
                }

                HttpUrl.Builder httpBuilder = HttpUrl.get(URI.create(urlData)).newBuilder();
                request.url(httpBuilder.build()); //TODO [httpBuilder 추가]
                // ------------------------------------------------------



                // ------------------------------------------------------
                // TODO [요청 로그 출력 실시]
                // ------------------------------------------------------
                S_Log._F_(mContext, "requestGetQueryStringHttp :: OK HTTP 비동기 GET [요청] 실시", new String[] {
                        "TAG :: " + String.valueOf(tag),
                        "TYPE :: " + "GET >> REQUEST",
                        "URL :: " + String.valueOf(urlData),
                        "HEADER :: " + String.valueOf(header),
                        "PARAMS :: " + String.valueOf(params)
                });
                // ------------------------------------------------------



                // ------------------------------------------------------
                // TODO [비동기 처리 (enqueue 사용)]
                // ------------------------------------------------------
                String finalUrlData = urlData;
                client.newCall(request.build()).enqueue(new Callback() {

                    // TODO [성공한 경우]
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        final String responseUrl = String.valueOf(finalUrlData);
                        final String responseHeader = String.valueOf(response.headers().toString());
                        final String responseCode = String.valueOf(response.code());
                        final String responseData = String.valueOf(response.body().string());


                        // ------------------------------------------------------
                        // [로그 출력]
                        // ------------------------------------------------------
                        S_Log._F_(mContext, "requestGetQueryStringHttp :: OK HTTP 비동기 GET [응답] 확인", new String[] {
                                "TAG :: " + String.valueOf(tag),
                                "TYPE :: " + "GET >> RESPONSE",
                                "CODE :: " + String.valueOf(responseCode),
                                "URL :: " + String.valueOf(responseUrl),
                                "HEADER :: " + String.valueOf(responseHeader),
                                "DATA :: " + String.valueOf(responseData)
                        });
                        // ------------------------------------------------------


                        // ------------------------------------------------------
                        // TODO [응답 코드 값 체크 및 리턴 데이터 반환]
                        // ------------------------------------------------------
                        try {
                            int statusCode = response.code();
                            if (statusCode >= 200 && statusCode < 300){ // TODO [정상 응답]

                                // TODO [결과 전송 실시]
                                subscriber.onNext(responseData);
                                subscriber.onComplete();

                            }
                            else { // TODO [에러 응답]
                                subscriber.onError(new Throwable("[ERROR] : : [requestGetQueryStringHttp] : " + C_ErrorCheck.getErrorHttpMsg(responseCode)));
                            }
                        }
                        catch (Exception e){
                            S_Log._printStackTrace_(mContext, S_FinalMsg.LOG_BUG_STATE, null, e);
                            subscriber.onError(new Throwable("[EXCEPTION] : [1] : [requestGetQueryStringHttp] : " + e.getMessage()));
                        }

                        // ------------------------------------------------------

                    }

                    //TODO [실패한 경우]
                    @Override
                    public void onFailure(Call call, IOException e) {
                        final String responseUrl = String.valueOf(finalUrlData);
                        final String responseError = String.valueOf(e.getMessage());


                        // ------------------------------------------------------
                        // [로그 출력]
                        // ------------------------------------------------------
                        S_Log._F_(mContext, "requestGetQueryStringHttp :: OK HTTP 비동기 GET [에러] 확인", new String[] {
                                "TAG :: " + String.valueOf(tag),
                                "TYPE :: " + "GET >> FAIL",
                                "URL :: " + String.valueOf(responseUrl),
                                "DATA :: " + String.valueOf(responseError)
                        });
                        // ------------------------------------------------------


                        // ------------------------------------------------------
                        // TODO [리턴 데이터 반환]
                        // ------------------------------------------------------
                        try {
                            subscriber.onError(new Throwable("[FAIL] : [requestGetQueryStringHttp] : " + responseError));
                        }
                        catch (Exception ex){
                            ex.printStackTrace();
                        }
                        // ------------------------------------------------------
                    }
                });

            } catch (final Exception e){
                // ------------------------------------------------------
                // [로그 출력]
                // ------------------------------------------------------
                S_Log._printStackTrace_(mContext, S_FinalMsg.LOG_BUG_STATE, new String[] {
                        "requestGetQueryStringHttp :: OK HTTP 비동기 GET [EXCEPTION] 확인",
                        "TAG :: " + String.valueOf(tag),
                        "TYPE :: " + "GET >> EXCEPTION",
                        "EXCEPTION :: " + String.valueOf(e.getMessage())
                }, e);
                // ------------------------------------------------------


                // ------------------------------------------------------
                // TODO [리턴 데이터 반환]
                // ------------------------------------------------------
                try {
                    subscriber.onError(new Throwable("[EXCEPTION] : [2] : [requestGetQueryStringHttp] : " + String.valueOf(e.getMessage())));
                }
                catch (Exception ex){
                    ex.printStackTrace();
                }
                // ------------------------------------------------------
            }

        });
    }
 

[결과 출력]

 

W///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.A_Intro$2.onNext(A_Intro.java:408)]
I/: ----------------------------------------------------
I/: [LOG :: NOW TIME :: 2023-10-16 15:45:14 월요일]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: http :: onNext]
I/: ----------------------------------------------------
I/: [LOG :: COUNT :: 3]
I/: ----------------------------------------------------
I/: [LOG :: VALUE :: [
      {
        "userId": 1,
        "id": 1,
        "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
        "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
      }
    ]]
W///===========//: ================================================



W///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.A_Intro$2.onNext(A_Intro.java:408)]
I/: ----------------------------------------------------
I/: [LOG :: NOW TIME :: 2023-10-16 15:45:17 월요일]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: http :: onNext]
I/: ----------------------------------------------------
I/: [LOG :: COUNT :: 2]
I/: ----------------------------------------------------
I/: [LOG :: VALUE :: [
      {
        "userId": 1,
        "id": 1,
        "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
        "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
      }
    ]]
W///===========//: ================================================



W///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.A_Intro$2.onNext(A_Intro.java:408)]
I/: ----------------------------------------------------
I/: [LOG :: NOW TIME :: 2023-10-16 15:45:21 월요일]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: http :: onNext]
I/: ----------------------------------------------------
I/: [LOG :: COUNT :: 1]
I/: ----------------------------------------------------
I/: [LOG :: VALUE :: [
      {
        "userId": 1,
        "id": 1,
        "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
        "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
      }
    ]]
W///===========//: ================================================



E///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.A_Intro$2.onNext(A_Intro.java:415)]
I/: ----------------------------------------------------
I/: [LOG :: NOW TIME :: 2023-10-16 15:45:21 월요일]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: http :: onNext]
I/: ----------------------------------------------------
I/: [LOG :: Polling Count End]
E///===========//: ================================================

 

반응형
Comments