투케이2K

76. (TWOK/ALGORITHM) [RxJava] 패턴 - MVI (Model , View , Intent) 형태 로직 구현 실시 본문

투케이2K 알고리즘

76. (TWOK/ALGORITHM) [RxJava] 패턴 - MVI (Model , View , Intent) 형태 로직 구현 실시

투케이2K 2023. 1. 3. 07:13

[환경 설정 및 설명]

언 어 : RxJava

설 명 : 패턴 - MVI (Model , View , Intent) 형태 로직 구현 실시

 
 
 

[클래스 구조]

1. Activity : 뷰 화면, 모델 상태 업데이트 시 렌더링을 수행해 다시 변경된 데이터 사용자에게 표시

2. Intent : 이벤트 동작 정의, 앱 상태 변경 요청 전달

3. Handler : 인텐트와 모델 중간 사이 위치해 비즈니스 로직 처리 및 모델 상태 업데이트, 인텐트로 모델 상태 알림 전달

4. Model : 모델 데이터 상태 값 저장
 

[로직 흐름 설명]

    /**
     * // --------------------------------------------------------------------------------------
     * TODO [로직 흐름]
     * // --------------------------------------------------------------------------------------
     * [1] : Activity : 사용자가 버튼 클릭 동작 실시
     * [2] : Activity : 버튼 클릭 이벤트 발생 시 >> Intent 이벤트 호출 실시
     * [3] : Intent : Intent 에서는 세부 로직 처리 및 Model 데이터 업데이트를 위한 Handler 호출
     * [4] : Handler : Handler 에서는 세부 로직 처리 및 Model 데이터 업데이트
     * [5] : Handler : Handler Model 업데이트 이후 >> Intent 로 데이터 변경 상태 알림 전달
     * [6] : Intent : Handler 로부터 알림을 전달 받으면 >> Activity 렌더링 화면 호출 실시
     * [7] : Activity : 렌더링 명령이 내려오면 화면 UI 갱신 실시
     * // --------------------------------------------------------------------------------------
     */
 

[Activity : 소스 코드]

package com.example.javaproject.TestCode.Mvi;

import android.os.Bundle;

import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.example.javaproject.R;
import com.example.javaproject.TestCode.A_Test;

public class Activity extends AppCompatActivity {



    /**
     * // --------------------------------------------------------------------------------------
     * TODO [클래스 설명]
     * // --------------------------------------------------------------------------------------
     * 1. 인트로 로딩 화면 액티비티
     * // --------------------------------------------------------------------------------------
     * */





    /**
     * // --------------------------------------------------------------------------------------
     * TODO [빠른 로직 찾기 : 주석 로직 찾기]
     * // --------------------------------------------------------------------------------------
     * // [SEARCH FAST] : []
     * // --------------------------------------------------------------------------------------
     */





    /**
     * // --------------------------------------------------------------------------------------
     * TODO [로직 흐름]
     * // --------------------------------------------------------------------------------------
     * [1] : Activity : 사용자가 버튼 클릭 동작 실시
     * [2] : Activity : 버튼 클릭 이벤트 발생 시 >> Intent 이벤트 호출 실시
     * [3] : Intent : Intent 에서는 세부 로직 처리 및 Model 데이터 업데이트를 위한 Handler 호출
     * [4] : Handler : Handler 에서는 세부 로직 처리 및 Model 데이터 업데이트
     * [5] : Handler : Handler Model 업데이트 이후 >> Intent 로 데이터 변경 상태 알림 전달
     * [6] : Intent : Handler 로부터 알림을 전달 받으면 >> Activity 렌더링 화면 호출 실시
     * [7] : Activity : 렌더링 명령이 내려오면 화면 UI 갱신 실시
     * // --------------------------------------------------------------------------------------
     */





    // -----------------------------------------------------------------------------------------
    // TODO [컴포넌트 선언]
    // -----------------------------------------------------------------------------------------
    TextView user_text;
    EditText id_edit;
    EditText pw_edit;
    Button login_button;





    // -----------------------------------------------------------------------------------------
    // TODO [전역 변수]
    // -----------------------------------------------------------------------------------------
    private static final String ACTIVITY_NAME = "Activity";





    // -----------------------------------------------------------------------------------------
    // TODO [액티비티 onCreate]
    // -----------------------------------------------------------------------------------------
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        try {
            // [타이틀바 없애기 : FEATURE_NO_TITLE]
            requestWindowFeature(Window.FEATURE_NO_TITLE);
        }
        catch (Exception e){
            e.printStackTrace();
        }
        // [액티비티 레이아웃 지정 실시]
        setContentView(R.layout.activity_a_intro);
        Log.i("---","---");
        Log.d("//===========//","================================================");
        Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> onCreate() :: 액티비티 수행 실시]");
        Log.d("//===========//","================================================");
        Log.i("---","---");


        // TODO [1] : [컴포넌트 등록]
        user_text = (TextView) findViewById(R.id.user_text);
        user_text.setText("");

        id_edit = (EditText) findViewById(R.id.id_edit);
        id_edit.setText("twok");

        pw_edit = (EditText) findViewById(R.id.pw_edit);
        pw_edit.setText("admin");

        login_button = (Button) findViewById(R.id.login_button);


        // TODO [2] : [컴포넌트 이벤트 등록 실시]
        login_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // TODO [3] : 인텐트 전달 실시
                Intent.loginClick(Activity.this, id_edit.getText().toString(), pw_edit.getText().toString());
            }
        });


    } // TODO [메인 종료]





    // -----------------------------------------------------------------------------------------
    // TODO [4] : [사용자 로그인 ID 렌더링]
    // -----------------------------------------------------------------------------------------
    public void onRender(Activity activity, String data){
        Log.i("---","---");
        Log.d("//===========//","================================================");
        Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> onRender() :: 사용자 로그인 ID 렌더링]");
        Log.i("","\n"+"[data :: "+String.valueOf(data)+"]");
        Log.d("//===========//","================================================");
        Log.i("---","---");

        // [텍스트 뷰에 새로운 값 렌더링 실시]
        activity.user_text.setText(data);

    }





    // -----------------------------------------------------------------------------------------
    // TODO [액티비티 onResume]
    // -----------------------------------------------------------------------------------------
    @Override
    public void onResume(){
        super.onResume();
        Log.i("---","---");
        Log.d("//===========//","================================================");
        Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> onResume() :: 액티비티 실행 준비]");
        Log.d("//===========//","================================================");
        Log.i("---","---");
    }




    // -----------------------------------------------------------------------------------------
    // TODO [액티비티 onPause]
    // -----------------------------------------------------------------------------------------
    @Override
    public void onPause(){
        super.onPause();
        Log.i("---","---");
        Log.e("//===========//","================================================");
        Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> onPause() :: 액티비티 정지 상태]");
        Log.e("//===========//","================================================");
        Log.i("---","---");
    }




    // -----------------------------------------------------------------------------------------
    // TODO [액티비티 onDestroy]
    // -----------------------------------------------------------------------------------------
    @Override
    public void onDestroy(){
        super.onDestroy();
        Log.i("---","---");
        Log.e("//===========//","================================================");
        Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> onDestroy() :: 액티비티 종료 상태]");
        Log.e("//===========//","================================================");
        Log.i("---","---");
    }





    // -----------------------------------------------------------------------------------------
    // TODO [모바일 키 이벤트 발생 체크 부분]
    // -----------------------------------------------------------------------------------------
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // [모바일 디바이스의 뒤로가기 키 이벤트가 발생한 경우]
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            Log.i("---","---");
            Log.w("//===========//","================================================");
            Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> onKeyDown() :: 백버튼 터치시 뒤로 가기 이벤트 발생]");
            Log.w("//===========//","================================================");
            Log.i("---","---");

            // ------------------------------------
            // [액티비티 종료 실시]
            finish();
            overridePendingTransition(0, 0);
            // ------------------------------------
        }
        return true;
    }


} // TODO [클래스 종료]
 

[Intent : 소스 코드]

package com.example.javaproject.TestCode.Mvi;

import android.util.Log;

import io.reactivex.rxjava3.core.Observable;

public class Intent {

    // [이벤트 동작 정의 실시]
    public static void loginClick(Activity activity, String id, String pw){

        // [성공 및 실패 체크]
        boolean checkFlag = false;

        // [널 체크]
        if (id != null && id != "" && pw != null && pw != ""){
            checkFlag = true;
        }
        else {
            checkFlag = false;
        }

        // TODO [핸들러 로직 처리 및 액티비티 화면 렌더링 수행 실시]
        Observable<String> observable = new Handler().modelUpdate(checkFlag, id);
        observable.subscribe(
                value -> {
                    Log.i("---","---");
                    Log.d("//===========//","================================================");
                    Log.i("","\n"+"[Intent >> loginClick() :: subscribe :: onNext()]");
                    Log.i("","\n"+"-----------------------------------------");
                    Log.i("","\n"+"[value :: "+String.valueOf(value)+"]");
                    Log.d("//===========//","================================================");
                    Log.i("---","---");

                    // [액티비티 화면 렌더링]
                    new Activity().onRender(activity, String.valueOf(value));
                },
                error -> {
                    Log.i("---","---");
                    Log.e("//===========//","================================================");
                    Log.i("","\n"+"[Intent >> loginClick() :: subscribe :: onError()]");
                    Log.e("//===========//","================================================");
                    Log.i("---","---");
                },
                () -> {
                    Log.i("---","---");
                    Log.w("//===========//","================================================");
                    Log.i("","\n"+"[Intent >> loginClick() :: subscribe :: onComplete()]");
                    Log.w("//===========//","================================================");
                    Log.i("---","---");
                });
    }

} // TODO [클래스 종료]
 

[Handler : 소스 코드]

package com.example.javaproject.TestCode.Mvi;

import android.util.Log;

import io.reactivex.rxjava3.core.Observable;

public class Handler {

    // [전역 변수 선언]
    Model model = new Model();


    // [핸들러 로직 작성 : 모델 데이터 업데이트 / Intent 알림 전달]
    public Observable modelUpdate(boolean success, String name){
        Log.i("---","---");
        Log.d("//===========//","================================================");
        Log.i("","\n"+"[Handler >> modelUpdate() :: 모델 정보 업데이트]");
        Log.i("","\n"+"-----------------------------------------");
        Log.i("","\n"+"[name :: "+String.valueOf(name)+"]");
        Log.d("//===========//","================================================");
        Log.i("---","---");

        // TODO [모델 데이터 업데이트]
        if (success == true){ // [성공 >> 모델 데이터 업데이트 : 사용자 ID]
            model.setName(name);
        }
        else { // [실패 >> 모델 데이터 업데이트 : null]
            model.setName("error");
        }

        // TODO [구독자에게 알림 전달 실시 : Intent]
        return Observable.create(subscriber -> {
            try {
                if (subscriber.isDisposed() == false){ // [연결된 구독자가 있는 경우]

                    // [onNext] 데이터 알림 전달
                    subscriber.onNext(model.getName());

                    // [onCompleted] 완료 알림 전달
                    subscriber.onComplete();
                }
            }
            catch (Exception e){
                e.printStackTrace();
            }
        });
    }

} // TODO [클래스 종료]
 

[Model : 소스 코드]

package com.example.javaproject.TestCode.Mvi;

public class Model {

    // [전역 변수 선언]
    private String name = "";


    // [get 선언]
    public String getName(){
        return this.name;
    }


    // [set 선언]
    public void setName(String name){
        this.name = name;
    }


} // TODO [클래스 종료]
 

[결과 출력]

 

D///===========//: ================================================
I/: [Handler >> modelUpdate() :: 모델 정보 업데이트]
I/: -----------------------------------------
I/: [name :: twok]
D///===========//: ================================================

D///===========//: ================================================
I/: [Intent >> loginClick() :: subscribe :: onNext()]
I/: -----------------------------------------
I/: [value :: twok]
D///===========//: ================================================

D///===========//: ================================================
I/: [Activity >> onRender() :: 사용자 로그인 ID 렌더링]
I/: [data :: twok]
D///===========//: ================================================

 

반응형
Comments