Android MVVM 패턴 사용기

Assist·2023년 5월 17일
0

Android

목록 보기
9/21

요즘 사람인 , 잡코리아에서 안드로이드 개발자을 채용하는데 가장 많이 보이는게

주요요건 :
MVVM 패턴 구현 가능자
비동기 통신 구현 경험자
ETC... 일것이다.

사수 왈 : 디자인 패턴은 너한테 맞는걸 쓰면 된다
본인: 걍 MVVM이 짱 좋아서 사람들이 몰리는거 아님?
사수: 그럼 왜 MVC랑 싱글톤 패턴 etc가 아직도 살아 있을까
본인 : 그렇네
이렇듯 자기한테 맞고 시스템에 적합한 패턴을 골라야 한다
무조건 mvvm이 좋은게 아니다 하지만 mvvm 패턴을 공부하기로 했으니 일단 해보자
위 사진은 Android developer 라는 사이트에서 걸려있는 사진이다.
이해는 안되니 한번 상황을 가정해 보자
사용자 : 로그인 할래 아이디랑 비밀번호를 넘겨주지!
view (ID, password 가 "" 인지 혹은 값이 있는지 체크 !)
->ViewModel->repostiry한테 아이디 비번을 넘겨주고 토큰 받아와라 그럼 repostiry 은 비동기 통신으로 서버에 요청에서 토큰을 받아온다 라고 가정해 보자

일단 시작전 라이브러리 다운을 시작해보자

//viewModel
implementation "androidx.activity:activity-ktx:1.7.0"
implementation "androidx.fragment:fragment-ktx:1.5.6"
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1'
//retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

버전은 달라질수 있으니 유의 바란다

    val factory = LoginViewModelFactory(repository)
    viewModel = ViewModelProvider(this, factory)[LoginViewModel::class.java]
이코드는 무조건 해줘야 한다. 안그럼 생명주기가 안맞아
데이터를 지속적으로 요청해서 그게 viewModel에 쌓인다 
예 A(데이터 요청) -> B로이동 - >B에서 작업 마친후 A로 다시 
돌아가면 A(이전데이터 + 신규데이터) 로 필자는 같은 데이터가 2개가 
연속으로 배치된다. 다신 경험하기 싫은 일이다. 

여기서 factory은 viewModel에서 매개 변수가 필요할때 factory을 
사용해 viewModel에서 매개 변수를 사용할수 있게 된다 
필자는 repostory가 필요하니 factory에 repostiry을 넘겨줬다.
class LoginViewModelFactory(private val repository: LoginRepository) : ViewModelProvider.Factory{

   override fun <T : ViewModel> create(modelClass: Class<T>): T {
       if(modelClass.isAssignableFrom(LoginViewModel :: class.java)){
//            val repository = Repository(HomeAssetDataSource(AssetLoader(context)))
           return LoginViewModel(repository) as T
       }
       throw IllegalArgumentException("UnKnow ViewModel class")
   }
}

방금 설명한 factory이다. 잠깐 설명 하자면 이 factory은 LoginViewModel 만 사용할수 있다 만일 다른 viewModel이 넘어오면 즉시 예외 처리 한다.
LoginViewModel일시 매게변수로 넘어온 repository 을 viewModel에 넘겨주고 viewModel에서 repository 매게변수로 사용 가능해진다.

다음은 repository 이 코드이다

class LoginRepository {
  //로그인 요청
  fun requestLogin (data : UserInfo) = RetrofitInterface.retrofit.requestLogin(data)
}

해당 repository 은 이런식으로 필자는 만들었다 userInfo은 간단하게 생각해서 id , paassword가 들어있는 object라고 생각하면 된다.

그럼 viewModel은 ?

class LoginViewModel(val repostory : LoginRepositoty) : ViewMiodel() {

private var _loginLiveData = MutableLiveData<String>() 
prvate val _loginLiveData get()= _loginLiveData

fun requestLogin(id : String , passWord :String) = viewModelScope.launch{
	_loginLiveData.posValue("Loading")
	val data = UserInfo(id, password)
	val requestLogin = repostory.requestLogin(data)
  	requestLogin.enqueue(object  : Callback<String> {
           override fun onResponse(call: Call<String>, response: Response<String>) {
               if (response.isSuccessful) {
                   when (response.code()) {
                      200 -> {
                           val result = response.body()
                           if (result == null) {
                               _loginLiveData.postValue("MESSAGE_BODY_NULL"))
                               return
                           }
                        	
                          _loginLiveData.posValue("Success")
                       }
                       401->{
                           _loginLiveData.postValue("MESSAGE_UNAUTHORIZED")
                       }
                       else ->{
                           _loginLiveData.postValue("Data is Null" )
                       }
                   }
               }
           }
           override fun onFailure(call: Call<String >, t: Throwable) {
               _loginLiveData.postValue("error")
           }
       })
}

서버를 공부해본사람은 알것이다 .
보통 200 번이 okay
401와 404 가 error이다 그럼으로 필자도 그렇게 만들었다
위 함수는 retrofit을 이용한 함수이다. 그럼 repostory에서 요청한 데이터가 왔을데 repostory을 거쳐 viewModel에서 callback으로 만들어서 응답에 성공했는지 실패했는지를 알려준다.
그럼 liveData을 사용해보러 view로 가보자

    private fun addListener(){
    	viewModel.loginLiveData.observe(this,  Observer {
    		when(it) {
    			"Success -> //성공
    			"Data is Null" -> //데이터 이상
    			"MESSAGE_BODY_NULL" -> //데이터 이상 
    			"error" -> //error
    }
    
      ```
      
      
이런식으로 상황에 맞게 사용하면 된다. 여기서 this은 activity을 
가르킨것이다 LoginActivity. 그러고 Observer은 아까 ViewModel에서 
분기마다 다른데이터를 넣었는데 그 값이 바뀔떄마다 을 감시해
when ->자바로 따지면 switch문에서 따로 처리 해주는것이다. 

그럼 다음에는 네이버 책 api 로 한번 MVVM 패턴을 쭉 만들어 보겠다 
-그럼 이만- 
      
profile
안드로이드만 좋아하는 특이한 개발자

0개의 댓글