Android/Kotlin
안드로이드 Retrofit + MVVM + Repository + Dagger
easy-1
2021. 10. 20. 15:39
<개요>
Retrofit 을 이용한 서버통신을 할 때 MVVM + Repository + Dagger 를 적용하여 구현
<적용방법>
1. SignActivity
2. SignViewModel
3. SignModel
4. RetrofitService
5. NetworkModule
6. SignRepository
7. SignRepositoryImpl
<예제>
uid 값을 서버에 전송하고 success 값을 받아오는 예제
1) SignActivity.kt
- Activity 에서 ViewModel 을 등록
- userInfo 데이터를 Observe 하며 반응형 프로그래밍 작업
@AndroidEntryPoint
class SignActivity : AppCompatActivity() {
private lateinit var binding: ActivitySignBinding
private val viewModel by viewModels<SignViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_sign)
// Set Observer
observerViewModel()
viewModel.apiUserInfo()
}
// Set Observer
fun observerViewModel() {
viewModel.apply {
userInfo.observe(this@SignActivity, Observer {
Dlog.d("userInfo :: ${Gson().toJson(it)}")
})
}
}
}
2) SignViewModel.kt
- 관찰할 MutableLiveData userInfo 선언
- _userInfo 에 value 해줌으로써 userInfo 데이터 값이 변경됨
- Retrofit 을 이용한 서버 통신 후 Repository 에 저장된 데이터를 _userInfo 에 value 해줌
@HiltViewModel
class SignViewModel @Inject constructor(
private val service: RetrofitService
) : ViewModel() {
private val _userInfo: MutableLiveData<UserInfo> = MutableLiveData()
val userInfo: LiveData<UserInfo>
get() = _userInfo
// Retrofit을 이용하여 Repository에 저장된 데이터 가져오기
fun apiUserInfo() {
viewModelScope.launch {
val response = SignRepositoryImpl(service).getUserInfo(uid)
.awaitResponse()
if (response.isSuccessful) {
val data = response.body()
withContext(Main) {
if (data != null) {
Dlog.d("data :: ${Gson().toJson(data)}")
_userInfo.value = data
}
}
} else {
Dlog.d("failed :: ${response.message()}")
}
}
}
}
3) SignModel.kt
- Retrofit 을 이용한 서버통신 후 받아오는 리스폰값
data class UserInfo(
@SerializedName("success")
var success: Boolean = false,
)
4) RetrofitService.kt
- Retrofit 에 이용되는 interface
interface RetrofitService {
companion object {
const val BASE_URL =
"https://test.net/"
}
@FormUrlEncoded
@POST("userInfo.php")
fun get_userInfo(
@Field("uid") uid: String? = "",
): Call<UserInfo>
}
5) NetworkModule.kt
- Dagger 를 이용한 Retrofit 추가 설정
@Module
@InstallIn(SingletonComponent::class) //전체 application 에서 사용되는 모듈
object NetworkModule {
@Provides
@Singleton
fun provideRetrofitRepository(retrofit: Retrofit): RetrofitService {
return retrofit.create(RetrofitService::class.java)
}
@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(RetrofitService.BASE_URL)
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
}
@Provides
@Singleton
fun provideOkHttpClient(interceptors: ArrayList<Interceptor>): OkHttpClient {
val clientBuilder = OkHttpClient
.Builder()
.followRedirects(false)
interceptors.forEach {
clientBuilder.addInterceptor(it)
}
return clientBuilder.build()
}
@Provides
@Singleton
fun provideInterceptors(): ArrayList<Interceptor> {
val interceptors = arrayListOf<Interceptor>()
val loggingInterceptor = HttpLoggingInterceptor().apply {
level = if (BuildConfig.DEBUG) {
HttpLoggingInterceptor.Level.BODY
} else {
HttpLoggingInterceptor.Level.NONE
}
}
interceptors.add(loggingInterceptor)
return interceptors
}
}
6) SignRepository.kt
- Retrofit 통신 후 콜백 받아오는 Repository
interface SignRepository {
suspend fun getUserInfo(
uid: String? = "",
): Call<UserInfo>
}
7) SignRepositoryImpl.kt
- Repository 를 사용하여 구현
class SignRepositoryImpl @Inject constructor(
val service: RetrofitService
) : SignRepository {
override suspend fun getUserInfo(
uid: String?,
): Call<UserInfo> {
return service.get_userInfo(uid)
}
}