본문 바로가기
Android Application/응용 구현

안드로이드 회차별 로또 정보 받아오기(retrofit2 + MVVM)

by sdchjjj 2023. 4. 2.
728x90

안녕하세요.

이번 포스팅에서는 다른 포스팅에서 구현한 로또 정보 받아오는 소스에 MVVM 패턴을 적용해 보겠습니다.

의존성 주입은 hilt를 사용합니다.

 

retrofit2, mvvm, hilt 내용은 아래를 참고해 주세요.

https://it-of-fortune.tistory.com/30

 

안드로이드 retrofit2 사용(with Coroutine) - 로또 api 요청

안녕하세요. 이번 포스팅에서는 coroutine과 retrofit2를 심플하게 사용하여 회차별 로또 정보를 받아와 보겠습니다. 언어: 코틀린 sdk vsersion - compile: 33 - min: 21 - target: 33 dependency를 추가합니다. build.gr

it-of-fortune.tistory.com

https://it-of-fortune.tistory.com/27

 

안드로이드 MVVM 패턴 예시

안녕하세요. 이번 포스팅에서는 소프트웨어 디자인 패턴 중 하나인 mvvm 패턴을 안드로이드 앱을 통해 알아보겠습니다. MVVM 패턴에서 M은 Model, V는 View, VM은 ViewModel을 의미합니다. 쉽게 말해 V는 UI

it-of-fortune.tistory.com

https://it-of-fortune.tistory.com/26

 

안드로이드 힐트(hilt) 의존성 주입 구현

안녕하세요. 이번 포스팅에서는 hilt를 사용한 dependency injection을 간단하게 구현해 보겠습니다. 언어: 코틀린 sdk vsersion - compile: 33 - min: 21 - target: 33 저는 아래의 포스팅에서 사용한 소스에 적용해

it-of-fortune.tistory.com

 

언어: 코틀린

sdk vsersion

  - compile: 33

  - min: 21

  - target: 33

 

ViewModel class를 생성하여 아래와 같이 작성합니다.

Fragment에 작성했던 코드를 이곳으로 옮기고, 데이터 바인딩을 위한 코드를 추가했습니다.

LottoViewModel.kt

@HiltViewModel
class LottoViewModel @Inject constructor() : ViewModel() {

    private val _lottoResult = MutableLiveData<LottoData>()
    val lottoResult: LiveData<LottoData> get() = _lottoResult

    private var inputText: CharSequence = ""

    fun onTextInput(text: CharSequence) {
        inputText = text
    }

    fun onSearchClicked() {
        if (inputText.isNotEmpty()) {
            getDrawingResult()
        }
    }

    private fun getDrawingResult() {
        viewModelScope.launch(Dispatchers.IO) {
            _lottoResult.postValue(
                getLottoService().getDrawingResult(
                    method = "getLottoNumber",
                    drwNo = getDrwNo(inputText).toString()
                )
            )
        }
    }

    private fun getLottoService(): LottoService {
        return Retrofit.Builder()
            .client(OkHttpClient.Builder().build())
            .baseUrl("https://www.dhlottery.co.kr/")
            .addConverterFactory(
                MoshiConverterFactory.create()
            )
            .build()
            .create(LottoService::class.java)
    }

    private fun getDrwNo(text: CharSequence): Int{
        return text.toString().toInt()
    }
}

이번에는 숫자를 입력하고 검색 버튼을 누르면 해당 회차의 결과 정보를 받아옵니다.

getDrwNo에서 처음에 입력된 0을 걸러줍니다(ex: 0729 -> 729)

 

layout xml에 data binding을 추가합니다.

fragment_lotto.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="viewModel"
            type="com.example.laboratory.lotto.LottoViewModel" />

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".lotto.LottoFragment">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:gravity="center"
            android:inputType="number"
            android:maxLength="4"
            android:maxLines="1"
            android:onTextChanged="@{(s, start, before, count) -> viewModel.onTextInput(s)}"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="1004" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="검색"
            android:onClick="@{() -> viewModel.onSearchClicked()}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{viewModel.lottoResult.toString()}"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            tools:text="result" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

 

이로 인해 프래그먼트는 코드가 간략해졌습니다.

xml에 viewModel과 lifeCycleOwner를 알려주는 것이 전부입니다.

LottoFragment.kt

@AndroidEntryPoint
class LottoFragment : Fragment() {

    private var _binding: FragmentLottoBinding? = null
    private val binding get() = _binding!!

    private val viewModel: LottoViewModel by viewModels()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentLottoBinding.inflate(layoutInflater, container, false).apply {
            viewModel = this@LottoFragment.viewModel
            lifecycleOwner = viewLifecycleOwner
        }
        return binding.root
    }
}

 

에뮬레이터에서 테스트해 보겠습니다.

figure1. run

의도한 대로 잘 동작합니다.

 

이상 포스팅을 마치겠습니다.

 

감사합니다.

728x90

댓글