Android Application/응용 구현

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

sdchjjj 2023. 4. 2. 19:03
반응형

안녕하세요.

이번 포스팅에서는 다른 포스팅에서 구현한 로또 정보 받아오는 소스에 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
반응형