[2021.11.01] How to use Retrofit2 with android Using Kotlin?
우선 Retrofit2 개념을 간단하게 알아본 후, 안드로이드에서 고틀린과 함께 Retrofit2를 사용하는 방법에 대해 알아보자
https://square.github.io/retrofit/
-> Retrofit document
* Retrofit 이란?
-> REST API 통신을 위해 구현된 라이브러리
* Retrofit을 사용하는 이유?
-> 다른 라이브러리에 비해 간단한 구현 방법과 성능이 좋기 때문
-> 동기/비동기 방식을 선택, Call의 요청을 취소 가능
* Retrofit2 3가지 구성요소
DTO (POJO)
-> 'Data Transfer Object', 'Plain Old Java Object' 형태의 모델(Model) / JSON 타입변환에 사용
Interface
-> 사용할 HTTP CRUD동작(메소드) 들을 정의해놓은 인터페이스
* CRUD ( Create / Read / Update / Delete ) -> HTTP Method ( POST / GET / PUT / DELETE )
Retrofit.Builder 클래스
-> Interface를 사용할 인스턴스, baseUrl(URL) / Converter(변환기) 설정
* HTTP Method
POST : 리소스 생성
GET : 리소스 조회 및 출력
PUT : 리소스 수정
PATCH : 리소스 수정
DELETE : 리소스 삭제
* PUT과 PATCH 차이점
-> PUT은 해당 리소스의 전체를 교체, PATCH는 일부를 변경
HTTP 응답 코드
1xx : 요청을 받았으며 프로세스를 계속함 (정보)
2xx : 클라이언트의 요청을 정상적으로 수행 (성공)
3xx : 요청 완료를 위해 추가적인 작업 조치가 필요함 (리다이렉션)
4xx : 요청의 문법이 잘못되었거나 요청을 처리할 수 없음 (클라이언트 오류)
5xx : 서버가 명백히 유효한 요청에 대해 실패함 (서버 오류)
https://ko.wikipedia.org/wiki/HTTP_%EC%83%81%ED%83%9C_%EC%BD%94%EB%93%9C
-------------------------------------------------------------------------------------------------------------------------
Retrofit2 사용 방법
목차
1. 테스트 할 API (Github API)
2. DTO CLASS 생성
3. API Interface 생성
4. RetrofitBuilder 생성
5. API 확인을 위한 XML 작성
6. Activity에 API 호출
1. 테스트 할 API (Github API)
https://api.github.com/users/아이디
e.g : https://api.github.com/users/injekim97
* email,bio,followers 등 왼쪽에 있는 것들이 전부 key 값
--------------------------------------------------------------------------------------------------------------------------
2. DTO CLASS 생성
위의 사진을 보면 많은 정보가 있지만, 아이디와 팔로우, 팔로잉 수만 안드로이드 앱으로 가져오도록 해보자 .
* JSON 데이터를 받아올 UserInfo라는 DTO 클래스를 생성하자.,
* 변수의 이름을 JSON "키:값"과 이름을 맞춰 매핑하거나 @SerializedName을 통해 매핑 가능
New -> Kotlin Class/file
→ data class 클릭
* data class에 선언해 줄 코드(UserInfo.kt)
import com.google.gson.annotations.SerializedName //import 추가로 Unresolved reference: SerializedName 에러 해결
data class UserInfo(
@SerializedName("login")
val userId: String,
val blog: String,
val bio: String,
val public_repos: Int,
)
-> 유저 아이디, 팔로워 수, 팔로잉 수
* @SerializedName 에러를 해결 하려면?
implementation 'com.google.code.gson:gson:2.8.8' (2.9.0 버전은 에러 발생)
import com.google.gson.annotations.SerializedName
-> Unresolved reference: SerializedName 에러 해결
--------------------------------------------------------------------------------------------------------------------------
3. API Interface 생성
New -> Kotlin Class/file
→ interface 클릭
* interface 코드(API.kt)
import retrofit2.http.GET
interface API {
@GET("users/injekim97")// baseUrl + "user/{유저아이디}"
fun getUserInfo(
): retrofit2.Call<UserInfo>
}
* API 인터페이스를 생성 후 @을 이용하여 HTTP Method인 POST, GET, PUT, DELETE를 설정
@GET("users/injekim97") : injekim97 자신의 Github 아이디 입력
* Call을 불러올때 옆에 retrofit2가 적힌 것을 사용할 것
---------------------------------------------------------------------------------------------------------------------------------
4. RetrofitBuilder 생성
New -> Kotlin Class/file -> object
* RetrofitBuilder
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitBuilder{
lateinit var api : API
init{
val retrofit = Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
api = retrofit.create(API::class.java)
}
}
* 고정된 주소인 baseUrl에 https://api.github.com/ 입력
* .addConverterFactory()
-> GsonConverter를 추가하여 JSON 형식을 DTO Class 형식으로 자동변환
--------------------------------------------------------------------------------------------------------------------------------
5. API 확인을 위한 XML 작성
* 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0">
<TextView
android:id="@+id/bio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="60dp"
android:layout_marginEnd="60dp"
android:text="Bio"
android:textColor="#000000"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.434"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/login"
app:layout_constraintVertical_bias="0.476" />
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginEnd="18dp"
android:text="loading"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/publicRepos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="60dp"
android:layout_marginEnd="60dp"
android:text="repositories"
android:textColor="#000000"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.433"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/login"
app:layout_constraintVertical_bias="0.785" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="60dp"
android:layout_marginEnd="60dp"
android:layout_marginBottom="60dp"
android:text="Github API USE"
android:textColor="#000000"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.446"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.045" />
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="39dp"
android:layout_marginStart="88dp"
android:layout_marginEnd="146dp"
android:layout_marginBottom="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btn"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.025"
app:srcCompat="@drawable/github" />
<TextView
android:id="@+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="60dp"
android:layout_marginEnd="60dp"
android:layout_marginBottom="60dp"
android:text="User ID"
android:textColor="#000000"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.434"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3"
app:layout_constraintVertical_bias="0.149" />
<TextView
android:id="@+id/blog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="60dp"
android:layout_marginEnd="60dp"
android:text="Blog Address"
android:textColor="#000000"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.434"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/login"
app:layout_constraintVertical_bias="0.217" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
-----------------------------------------------------------------------------------------------------------------------------------
6. Activity에 API 호출
* MainActivity.kt
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.retrofit2.databinding.ActivityMainBinding
import com.google.gson.annotations.SerializedName
import retrofit2.Call
import retrofit2.Response
class MainActivity : AppCompatActivity() {
val mbinding by lazy { ActivityMainBinding.inflate(layoutInflater) } //뷰 바인딩
val TAG: String = "로그"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(mbinding.root)
mbinding.btn.setOnClickListener {
Toast.makeText(this, "Get the user's github info ", Toast.LENGTH_SHORT).show()
RetrofitBuilder.api.getUserInfo().enqueue(object : retrofit2.Callback<UserInfo> {
//통신 성공
override fun onResponse(call: Call<UserInfo>, response: Response<UserInfo>) {
val userinfo = response.body()!!
// ★★★★★ mbinding.id값.text = userinfo?.API 키값 ★★★★★
mbinding.login.text = userinfo?.userId
mbinding.blog.text = userinfo?.blog
mbinding.bio.text = userinfo?.bio
mbinding.publicRepos.text = userinfo?.public_repos.toString()
Log.d(TAG, "onResponse: 유저아이디: ${userinfo?.userId}, 블로그: ${userinfo?.blog}, 자기소개: ${userinfo?.bio}, 리포지토리 수: ${userinfo?.public_repos}")
}
//통신 실패
override fun onFailure(call: Call<UserInfo>, t: Throwable) {
Log.d("error", t.message.toString())
}
})
}
}
}
-> 뷰바인딩을 사용
* Callback 임포트 : retrofit2
참고 : https://www.notion.so/ViewBindingade69f4fe81c456a908c6e8cda722ce4
-----------------------------------------------------------------------------------------------------------------------------------
<실행 결과>
-> 정상적으로 아이디, blog 주소, 자기소개, 리포지토리 수가 출력된 것을 알 수 있다.
댓글