[Android/Kotlin] 안드로이드 로또 당첨번호 조회하기(2)
오늘은 회차별 로또 당첨번호를 가져오는 방법에서 대해서 알아보겠습니다.
회차별 로또번호를 조회하기 위해서는 아래 URL를 사용하시면 하시면 됩니다.
https://www.dhlottery.co.kr/common.do?method=getLottoNumber&drwNo=946
검색결과 아래와 같이 json 형태로 받아 볼 수 있습니다.
{"totSellamnt":99380178000,"returnValue":"success","drwNoDate":"2021-01-16","firstWinamnt":2157656182,"drwtNo6":40,"drwtNo4":30,"firstPrzwnerCo":11,"drwtNo5":34,"bnusNo":20,"firstAccumamnt":23734218002,"drwNo":946,"drwtNo2":18,"drwtNo3":19,"drwtNo1":9}
이걸 토대로 회차별로 로또 당첨번호를 조회하는 방법을 소개드립니다.
MVVM방식을 적용해서 파일이 좀 많습니다....
완성된 모습은 아래와 같습니다.
STEP01. build.gradle 추가하기
// Architectural Components
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
// Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation "com.squareup.okhttp3:logging-interceptor:4.5.0"
// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
STEP02. Retrofit 활용하기
Retrofit 사용법을 여기에서는 설명하지 않겠습니다.
[AndroidManifest.kt]
<uses-permission android:name="android.permission.INTERNET" />
[RetrofitInstance.kt]
class RetrofitInstance {
companion object {
private val retrofit by lazy {
val logging = HttpLoggingInterceptor()
logging.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient.Builder()
.addInterceptor(logging)
.build()
Retrofit.Builder()
.baseUrl("https://www.dhlottery.co.kr")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()
}
val api by lazy {
retrofit.create(LottoApi::class.java)
}
}
}
[LottoApi.kt]
interface LottoApi {
@GET("/common.do")
suspend fun getRecentWinningNumber(
@Query("drwNo") drwNum: Int,
@Query("method") method: String = "getLottoNumber"
): Response<LottoApiModel>
}
[LottoApiModel.kt]
data class LottoApiModel(
var drwNo: Int,
var drwNoDate: String,
var totSellamnt: Long,
var returnValue: String,
var firstWinamnt: Long,
var firstPrzwnerCo: Int,
var firstAccumamnt: Long,
var drwtNo1: Int,
var drwtNo2: Int,
var drwtNo3: Int,
var drwtNo4: Int,
var drwtNo5: Int,
var drwtNo6: Int,
var bnusNo: Int
)
STEP03. Repository 생성
로또 당첨번호 조회 요청을 담당하는 Repository 파일을 하나 만들어 줍니다.
[LottoRepository.kt]
class LottoRepository {
suspend fun getRecentWinningNumber(number: Int): Result<LottoApiModel> {
val response = RetrofitInstance.api.getRecentWinningNumber(number)
if (response.isSuccessful) {
response.body()?.let {
return Result.Success(it)
}
}
return Result.Error("error")
}
}
요청 결과를 Success() 또는 Error() 클래스로 리턴하도록 합니다.
[Result.kt]
sealed class Result<out T : Any> {
data class Success<out T : Any>(val data: T) : Result<T>()
data class Error(val error: String) : Result<Nothing>()
}
STEP04. ViewModel 생성
MainViewModel 클래스는 액티비티 대신 데이터 요청을 담당합니다.
[MainViewModel.kt]
class MainViewModel : ViewModel() {
val lottoRepository = LottoRepository()
private val _lottoApiResponseLiveData = MutableLiveData<LottoApiResponse>()
val lottoApiResponseLiveData: MutableLiveData<LottoApiResponse> get() = _lottoApiResponseLiveData
fun getRecentWinningNumber(number: Int) = viewModelScope.launch {
_lottoApiResponseLiveData.value = LottoApiResponse.loading()
when (val result = lottoRepository.getRecentWinningNumber(number)) {
is Result.Success -> {
_lottoApiResponseLiveData.value = LottoApiResponse.success(result.data)
}
is Result.Error -> {
_lottoApiResponseLiveData.value = LottoApiResponse.error(result.error)
}
}
}
}
LottoApiResponse 클래스를 만들어 요청 결과를 반환합니다.
액티비티에서 loading(), success(), error()에 따라서 유용하게 사용할 수 있습니다.
[LottoApiResponse.kt]
data class LottoApiResponse(
val status: Status,
val data: LottoApiModel?,
val error: String?
) {
companion object {
fun loading(): LottoApiResponse = LottoApiResponse(Status.LOADING, null, null)
fun success(lotto: LottoApiModel): LottoApiResponse =
LottoApiResponse(Status.SUCCESS, lotto, null)
fun error(error: String): LottoApiResponse =
LottoApiResponse(Status.ERROR, null, error)
}
}
enum class인 Status를 만들어 상태를 저장합니다.
[LottoApiResponse.kt]
enum class Status {
LOADING,
SUCCESS,
ERROR
}
STEP05. 호출하기
회차를 입력하고 조회하기 버튼을 클릭하면 해당회차 로또 담청번호를 조회할 수 있습니다.
viewmodel에 정의한 lottoApiResponseLiveData를 관찰하고 그 변화에 따라 view를 변경해 줍니다.
[MainActivity.kt]
class MainActivity : AppCompatActivity() {
private val mainViewModel by lazy {
ViewModelProvider(this).get(MainViewModel::class.java)
}
private var _binding: ActivityMainBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.btnSearch.setOnClickListener {
mainViewModel.getRecentWinningNumber(binding.edtRound.text.toString().toInt())
}
mainViewModel.lottoApiResponseLiveData.observe(this) { response ->
when (response.status) {
Status.LOADING -> {
}
Status.SUCCESS -> {
response.data?.let { lotto ->
binding.txtDate.text = lotto.drwNoDate
binding.txtNumber.text = "${lotto.drwtNo1} ${lotto.drwtNo2} " +
"${lotto.drwtNo3} ${lotto.drwtNo4} ${lotto.drwtNo5} ${lotto.drwtNo6} "
}
}
Status.ERROR -> {
}
}
}
}
override fun onDestroy() {
super.onDestroy()
_binding = null
}
}
[activity_main.xml]
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/txt_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:textSize="22sp"
android:textStyle="bold"
android:textAlignment="center"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="2021-01-16"/>
<TextView
android:id="@+id/txt_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:textSize="18sp"
android:textStyle="bold"
android:textAlignment="center"
app:layout_constraintTop_toBottomOf="@+id/txt_date"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:text="2 19 24 32 38 45"/>
<EditText
android:id="@+id/edt_round"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:hint="회차"
android:inputType="number"
app:layout_constraintTop_toBottomOf="@+id/txt_number"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<Button
android:id="@+id/btn_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="조회하기"
app:layout_constraintTop_toBottomOf="@+id/edt_round"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
플레이스토어 링크: https://play.google.com/store/apps/details?id=com.reachfree.numberonelotto
'기리's Android 이야기' 카테고리의 다른 글
[Android/Error] 안드로이드 Caused by: java.lang.NullPointerException: Missing required view with ID: ~~~~~ (3) | 2021.01.21 |
---|---|
[Android/Kotlin] 안드로이드 SharedPreferences 사용하기 (3) | 2021.01.20 |
[Android/Kotlin] 안드로이드 로또 번호 생성하기(1) (1) | 2021.01.17 |
[앱소개/로또앱] 넘버원로또 소개 (4) | 2021.01.17 |
[Android/Java] 안드로이드 ViewPage2 무한 이미지 슬라이딩 구현하기 (10) | 2021.01.15 |
댓글