좋습니다 이제 Service가 준비되었으니 viewmodel에 대해 다뤄봅시다
이는 데이터와 우리의 주된 활동인 실질적인 view를 담당합니다
그리고 조금 나중에 우리 앱의 디자인 측면도 보도록하겠습니다
하지만 지금은 viewmodel을 설정해 봅시다
새로운 Class MainViewmodel을
만들어줍니다
좋습니다
이것은 우리의 mainView에 대한 viewmodel이 될 것입니다
그리고 viewmodel 유형이 될 것입니다
좋습니다
Viewmodel
좋습니다
이는 androidx.lifecycle 안에 있습니다
여기에 괄호를 추가해야 합니다
좋습니다
이제 이 mainViewModel 안에 recipe의 상태를 다루는 데이터 클래스를
만들어 봅시다
우리는 레시피가 있는지에 대한 여부와 다운로드 상태가 어떤지에 대해 알아야 합니다
로딩을 하고 있는가? 아닌가?
리스트가 있는가? 없는가?
에러가 발생하였는가? 안 하였는가?
그러므로 기본적으로 이를 다루게 될 데이터 클래스를 만들겠습니다
그리고 그것은 recipeState입니다
좋아요
자 그래서 여기에 중괄호가 있으면 안됩니다
데이터 클래스니까요
그래서 val loading: boolean을 입력합니다
그리고 기본 설정으로 true를 사용합니다
category 유형의 리스트를 만듭니다
카테고리를 표시하려는 목적입니다
그리고 이것의 시작을 emptyList로 정의합니다
기본 값으로 emptyList를 지정합니다
그리고 string?=nullable인 에러를 작성합니다
에러가 현재 없습니다
그래서 에러가 없는 경우에 null이 표시되도록 하는 것입니다
그래서 error는 null이고 비어 있다는 것입니다
그리고 변수를 null로 두거나 null로 될 수 있도록 하고 싶다면
데이터 유형 뒤에 물음표를 사용하셔야 합니다
이 경우에는 string?을 사용하여 해당 문자열이 nullable이 되도록 합니다
그렇게 해서 = null이 성립하도록 말입니다
null이 될 수 있는 것입니다
그러니 이는 null-able이 될 수 있는 null lable 입니다(언어유희)
영어는 멋진 언어입니다
자 이제 recipeState가 있으니
main viewmodel에 categorieState라고 하는 global 변수를 만들어줍니다
그리고 mutablestateof(recipeState)를
이걸로 합시다
작성해줍니다
간단하게 말하면 우리만의 state를 만들었습니다
작동하게 하려면 괄호를 추가할 필요가 있습니다
그래서 이것은 객체 유형 혹은 .클래스입니다
그리고 우리는 모든 종류의 데이터 유형에 mutableStateof를 사용할 수 있다는 것을 확인했습니다
문자열, boolean, 정수(Ints) 뿐만 아니라 저희가 만든 데이터 클래스도 포함해서 말입니다
이제 또 하나의 val CategoriesState를 만들고
recipeState 유형의 State를 넣어줍니다
그리고 이는 categorieState가 뭐든 일치할 것입니다
이제 제대로 작동하려면 state를 import해줘야 합니다
State를 import 해봅시다
잠시 올바른 state를 가져오는지 확인하겠습니다
우리가 사용할 것은 Androidx.compose.runtime입니다
어디일까요
Compose runtime...
이 State입니다
여기 있는 것입니다
올바른 import를 하는 것은 정말 중요합니다
제가 가진것과 같도록 꼭 확인해줘야 합니다
그러지 않으면 에러가 발생하거나 아주 혼란스러워질 것입니다
여기 이런 에러는 정말 이해하기 힘들 것입니다
좋습니다 우리는 이 private 변수를 만들고 public 변수를 만듭니다
이는 이에 액세스 하려는 다른 클래스에 노출될 변수입니다
그리고 categoriesState가 State유형이라는 것을 볼 수 있습니다
즉 구성 가능한 함수를 실행하는 동안 값 속성을 참조하는 value holder는
현재의 재구성 범위가 해당 값의 변화에 따르게 되고 이는 기본적으로
실제로 우리의 recipeState 객체가 변경될 때마다 사용자 인터페이스가
업데이트 되기를 원한 다는 것입니다
따라서 객체가 업데이트되거나 리스트가 업데이트 되면 리스트를 다운로드하고
마침내 그것을 사용할 수 있습니다
우리는 그것을 화면에 표시하고 싶고 그리고 화면에 무언가를 표시하기 위해서는
State를 변경해야하거나 State 자체가 변경되었으니 UI를
새로 고침해야 한다는 것을 읽을 수 있어야 하고 그걸 위해 설정을 하고 준비를
하는 것입니다
이제 카테고리를 fetch하기 위한 메서드가 필요합니다
그리고 제가 말씀 드렸듯이 viewmodel은 데이터와 UI 간의 통신을 처리합니다
간단하게 말하면 UI가 작업할 수 있도록 모든 것을 준비합니다
그러므로 카테고리를 fetch 할 수 있는 함수를 설정할 것입니다
그럼 이제 private fun fetchCategories를 만듭니다
fetch란 무언가를 가져온다는 표현입니다
코딩할 때 자주 사용하는 키워드입니다
여기서는 viewModel scope라는 것을 사용할 것입니다
viewModel scope는 suspend 함수가 처리되도록 launch를 제공합니다
앞서 말씀 드렸듯이
suspend 함수는 기본적으로 백그라운드에서 실행되는 것입니다
그러므로 main thread를 하단하지 않습니다
기본적으로 백그라운드에서 작업을 수행합니다
그리고 suspend 함수를 시작하고 싶다면 coroutine 내에서 시작해야 합니다
제가 말씀 드렸듯이 말입니다
이를 위해서 우리는 viewModel scope를 사용합니다
viewModelScope를 작성합니다
그리고 main viewModel 안에 viewModelScope를 만들고
lifecycle.viewModelScope를 import할 필요가 있습니다
그러면 launch할 수 있습니다
그래서 launch 메서드를 사용해 줍니다
그리고 중괄호 안에
이제 코드를 실행할 수 있는 곳인데
그래서 coroutine scope 말입니다
앞서 언급한 키워드인 coroutine은 말입니다
coroutine은 백그라운드에서 routine을 실행하고 코드를 실행할 수 있게 해줍니다
여기서 제가 할 일은 try and catch를 실행하는 것입니다
그래서 try and catch는 에러가 있는 경우에
프로그램이 충돌하는 것을 막기 위해 사용하는 것입니다
그래서 이것이 바로 try and catch가 하는 일입니다
이것은 무언가 잘못되면
해당 에러를 catch하고 우리에게 문제에 대해 알려주거나 에러가 발생했다고 알려줍니다
어떤 에러를 가질지 정해야합니다
여기에 e: exception을 호출합니다
자 그래서 매우 일반적인 예외라는 것이 있습니다
이는 모든 예외를 말하며 나타날 수 있는 모든 에러를 다룹니다
그 다음 에러가 발생한다면 무엇을 할 것인가에 대해 작성해야 합니다
categorieStae.Value = catergorieState.value.copy라고 적어줍니다
그리고 여기에 loading을 false로 설정합니다
그리고 에러를 표시할 것입니다
error = error fetching categories를 작성해줍니다
그리고 e.message를 추가합니다
fetching을 작성하는 것은 안전할 것입니다
그래서 이것이 수행하는 작업은 오류가 있는 경우, error fetching categories와
에러 메시지를 보여줄 것입니다
그래서 여기 e, 이 예외는 에러 메시지를 포함합니다
그리고 print that out과 같은 것을 작성할 수 있습니다
그래서 에러를 표시하고 싶다면 error 안에 넣으면 되고
이는 단순하게 recipeState의 에러에 액세스하면 됩니다
왜냐하면 여기 copy의 일이 그것이기 때문입니다
이는 recipeState의 mutableState인 categoryState의 값을 가져옵니다
그래서 간단하게 말하면 오버라이딩을 하면서 더이상 로딩을 하지 않는다고 하는 것입니다
그러니 실패했기에 로딩을 false로 설정하고 에러 안에 메시지를 표시하는 것입니다
그러니 여기 error: String?은 발생한 에러로 가득 차게 됩니다
그래서 지금까지가 에러가 발생하면 일어나는 일에 대한 설명이었습니다
자 그럼 어떤 일이 일어나야 하는 가
다시 말해, 정상적으로는 어때야 하는 가에 대해 살펴볼 것입니다
왜냐하면 인터넷으로 하던 스마트폰으로 하던 잘못될 수 있기에 try and catch를
사용할 것이기 때문입니다
그러니까 코드를 try와 catch로 둘러 싸는 것입니다
기본적으로 에러 발생 시 프로그램이 충돌하지 않고 앱이 충돌하지 않도록 방지하기 위함입니다
예를 들어, 인터넷 연결이 없거나 웹사이트가 삭제되는 경우, URL은 작동하지 않을 것입니다 이게 아니라면
잘못될 수 있는 어떤 경우건
catch될 필요가 있습니다
그 일을 여기서 하는 것입니다
하지만 먼저 try를 설정합니다
자 이제 try reponse에 recipeService.getCategories를 작성합니다
그 다음 categoriestate를 사용해서 value에 응답된 값이면 뭐든지로 설정합니다
이 응답은 여기에서 이 메서드를 호출한다는 의미입니다
여기 recipeService를 초출하고 getCategories를 말입니다
그래서 이 recipeService는 사용될 수 있도록 유출시키는 변수입니다
이것은 우리의 Api service 안에 있는 것입니다
그리고 우리의 Api service는 여기 getCategories라는 함수가 있다라는 것을 말해줍니다
그리고 그것이 응답할 때는 카테고리 리스트를 포함하는 categoriesResponse를 사용합니다
좋습니다
자 이제 카테고리를 받았고 response도 받았습니다 이제 복사하면 됩니다
value를 작성합니다 categorieState의 값을 받고 복사합니다
그러나 response.categories로 오버라이드 하고 로딩을 false로 설정합니다
그리고 에러를 null로 설정해 줍니다
따라서 기본적으로 카테고리의 리스트를 포함한 recipe state의 유형인
categorieState를
이 모든 categories를 줄 것입니다
categories는 response 안에 있습니다
그래서 인터넷에서 받는 response가 있고
스마트폰 안에서 response를 처리하는 방법이 있습니다
그리고 response를 처리하기 위해서, service로부터 얻던 response 항목과
응답 항목의 리스트를 얻는 state를 사용합니다
우리는 Service를 이용합니다
이 함수는 무슨 일이 벌어지는 지에 대해 아주 복잡하기 때문에 한번 더 설명하겠습니다
이번 것을 이해하고 나면
앞으로 나아가도 문제 없을 것입니다
좋습니다
그럼 이제 categories를 가져와서 이 response 변수 안에 보관합니다
이제 이를 사용하여 categorieState를 오버라이드 할 수 있습니다 이는 카테고리의 세부사항을
자체적으로 포함하는 recipleState에 대한 사용자 인터페이스를 업데이트 하는 것입니다
그런 다음 저것들을 표시할 수 있습니다
그러기 위해서는 다음 영상에서 설정을 해야 할 것입니다
좋습니다
보시면 더이상 로딩하지 않는다고 해놓았습니다
에러가 없다면 그대로 진행이 될 것입니다
자 이제 이 fetch categories는 무엇이 되었건 표시하기 위해서 호출해야 하는
함수가 될 것입니다
데이터를 받고 스마트폰에 보관하기 위해서 말입니다
그리고 이제 다음 단계는 보관한 곳으로부터 데이터를 표시하는 것이 되겠습니다
.initialization에서 fetchCategories를 작성합니다
그래서 main viewModel이 사용되는 순간, 카테고리를 가져오고 싶습니다
이 getCategories인 suspend 함수를 호출하는 코드 routine을 실행합니다
이는 suspend 키를 사용하고 retrofit을 사용해서 인터넷으로부터 카테고리를 가져옵니다
그리고 이 recipeService는 여기 getCategories 함수를 사용하게 해줍니다
이 시점에서 main viewmodel에서 사용하고 있을 것입니다
그리고 나서 recipeState 객체로 데이터를 채울 수 있게 해주고
mutableState로 만들거나 보내져서 UI를 변경하게 해줍니다
정말 많은 일이 일어나며 이 변수는 외부의 변수로
노출시켜줄 것입니다
예를 들어, main activity나 coposable 말입니다
이는 모든 사용자 인터페이스를 다룹니다 왜냐하면 나중에 우리의 main activity 안에
composable을 호출할 것이기 때문입니다
좋습니다
전체 프로젝트가 완료되면 전체 흐름을 살펴보겠습니다
하지만 지금은 여기까지만 하고 다음 영상으로 찾아뵙겠습니다