안드로이드 retrofit2, moshi, 코루틴을 이용한 비동기 rest api 호출하기
개발환경
프로젝트 생성
Empty Activity 선택
Language를 Kotlin으로 선택
Minimum SDK API21 선택 후 Finish 클릭
의존성 추가
//retrofit2
implementation 'com.squareup.retrofit2:retrofit:2.7.1'
implementation 'com.squareup.retrofit2:converter-moshi:2.7.1'
def lifecycle_version = "2.2.0"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
com.squareup.retrofit2:retrofit는 retrofit2를 사용하기 위한 라이브러리
com.squareup.retrofit2:converter-moshi는 json 문자열을 data class로 자동변환 해주기 위한 라이브러리
androidx.lifecycle:lifecycle-runtime-ktx 코루틴을 사용하기 위한 라이브러리
data class 작성
https://jsonplaceholder.typicode.com/todos/1 리턴되는 json을 object로 컨버팅 합니다.
해당 url을 요청해 보면
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}
위와 같은 구조의 데이터를 response 해줍니다.
각각의 propery에 대응하는 data class를 생성합니다.
data class Todo(
var userId: Int,
var id: Int,
var title: String,
var completed: Boolean
)
Endpoint class 작성
interface TodoService {
@GET("/todos/{userId}")
fun get(@Path("userId") userId: Int) : Call<Todo>
companion object {
const val BASE_URL = "https://jsonplaceholder.typicode.com"
}
}
@Path는 endpoint의 {userId}를 파라메터 값으로 변환시켜 줄 때 사용합니다.
BASE_URL는 변하는 않는 host이므로 companion object로 정의합니다.
MainActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val retrofit = Retrofit.Builder()
.baseUrl(TodoService.BASE_URL)
.addConverterFactory(MoshiConverterFactory.create())
.build();
val todoService = retrofit.create(TodoService::class.java)
todoService.get(1).enqueue(object: Callback<Todo> {
override fun onFailure(call: Call<Todo>?, t: Throwable?) {
Log.v("retrofit", "call failed")
}
override fun onResponse(call: Call<Todo>?, response: Response<Todo>?) {val todo: Todo? = response?.body()}
textView.text = todo.toString()
})
}
}
- Retrofit 인스턴스를 생성합니다.
- Retrofit 인스턴스를 통해 endpoint가 정의된 TodoService를 생성합니다.
- enqueue 메소드는 비동기로 처리됩니다.
- 전송 될 데이터가 response?.body()에 Todo로 컨버팅 됩니다.
비동기 request를 코루틴으로 처리하기
interface TodoService {
@GET("/todos/{userId}")
fun get(@Path("userId") userId: Int) : Call<Todo>
@GET("/todos/{userId}")
suspend fun getSuspend(@Path("userId") userId: Int) : Todo
companion object {
const val BASE_URL = "https://jsonplaceholder.typicode.com"
}
}
getSuspend 메소드를 정의합니다. suspend 키워드가 필요하며 Call 삭제 합니다.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val retrofit = Retrofit.Builder()
.baseUrl(TodoService.BASE_URL)
.addConverterFactory(MoshiConverterFactory.create())
.build();
val todoService = retrofit.create(TodoService::class.java)
CoroutineScope(Dispatchers.Main).launch {
val todo = todoService.getSuspend(1);
textView2.text = todo.toString()
}
}
}
suspend 메소드는 CoroutineScope(Dispatchers.Main).launch 블럭 안에서 실행시켜야 합니다. 코루틴을 사용하게 되면 비동기 처리를 동기 처리와 같은 느낌으로 코딩이 가능하게 되며 코드가 간결해 집니다.


안녕하세요! 혹시 실패처리는 어떻게하나요 ??
답글삭제