1. retrofit2와 okhttp3, gson 빌더를 싱글톤으로 생성한다
빌더를 만드는 것은 한 번 만들고 다시 코드를 적을일 없으니 저장해놓고 쓰도록 하자.
import com.connple.weat.api.model.Notification
import com.connple.weat.api.model.User
import okhttp3.MultipartBody
import retrofit2.Call
import retrofit2.http.*
object MyApp {
private lateinit var retrofit: Retrofit
private val signedIn get() = authToken != null
fun update(
baseUrl: String? = null,
authToken: String? = null
) {
MyApp.authToken = authToken ?: MyApp.authToken
val retrofitBuilder = Retrofit.Builder()
val clientBuilder = OkHttpClient.Builder()
if (signedIn) clientBuilder.addInterceptor(AuthorizationHeaderInterceptor(MyApp.authToken!!))
val GsonBuilder = GsonBuilder().setLenient()
retrofitBuilder.baseUrl(MyApp.baseUrl)
.client(clientBuilder.build())
.addConverterFactory(GsonConverterFactory.create(gsonBuilder.create()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
retrofit = retrofitBuilder.build()
me = retrofit.create(MeService::class.java)
}
init{
update()
}
AuthorizationHeaderInterceptor(private val authToken: String) : Interceptor{
override fun intercept(chain: Interceptor.Chain): Response{
val resquestBuilder = chain.request().newBuilder()
requestBuilder.removeHeader("authorization").addHeader("authorization", authToken)
return chain.proceed(requestBuilder.build())
}
}
2. retrofit2의 서비스 인터페이스를 만든다.
interface MeService{
@GET("user")
fun get(): Call<User>
@GET("user/{:id}/following")
fun getFollowing(@Path("id") id: Int) : Call<List<Following>>
@GET("users")
fun getUsers(@Query("cursor") cursor: Int) : Call<List<User>>
@FormUrlEncoded
@POST("user")
fun update(@Field("id") id: Int,
@Field("username") username: String
) : Call<User>
}
@GET, @POST, @PUT, @DELETE 이렇게 네가지 메소드를 사용할 수 있는데 사용법은 위와 같다.
주로 사용하는 태그는 @Path, @Query, @Field, @Body 가 있다.
url에 인자를 넣는 법은 {:id}와 같이 넣으면 되고 @Path 어노테이션을 붙여서 요청한다.
쿼리는 @Query 어노테이션을 붙여서 사용하면 된다.
@Field의 @FormUrlEncoded는 인자를 key=value&key=value 형식으로 보내는 것이고 @Field("key") value: Any와 같은 형식으로 사용하면 된다.
@FormUrlEncoded는 @Field를 이용하기 위해서 꼭 필요한 어노테이션이다.
@Body 태그도 존재하는데 이는 key=value 형식이 아닌 http 헤더의 body에 담아서 보내는 것이다.
3. 만든 인터페이스를 이용해서 웹 요청을 보낸다.
인터페이스를 사용하는 방식은 두 가지가 있다. 안드로이드는 기본적으로 메인 스레드에서 네트워크 요청을 보내지 못하기 때문에 따로 스레드를 생성해서 네트워크 요청을 하는데 레트로핏에서는 기본적으로 네트워크 요청을 보내는 함수를 지원한다.
레트로핏에서 지원하는 함수
MyApp.me.get().enqueue(object : Callback<User> {
override fun onResponse(call: Call<User>, response: Response<User>) {
val value = response.body()
}
override fun onFailure(call: Call<User>, t: Throwable) {
println("네트워크 요청 실패")
}
})
지원하는 함수를 사용하지 않고 만들기 위해서는 따로 스레드를 만들거나 코루틴을 이용해야 한다.
나는 주로 코루틴을 이용하므로 코루틴을 이용한 코드로 예시를 넣었다.
GlobalScope.launch(Dispatchers.IO) {
val response = MyApp.me.get().execute()
if(response.isSuccessful) {
val value = response.body()
}else{
// 실패시 할 작업
}
}
GlobalScope란 코루틴이 분리되어 존재할 범위를 나타내는 것이고 .launch는 코루틴을 실행하는 것이다.
(Dispatchers.IO)에서 Dispatcher는 코루틴에서 사용할 스레드를 고른다. 스레드에는 IO, Main, Default가 있다.
안드로이드는 정책 상 메인 스레드에서 네트워크 요청을 보내지 못하므로 IO스레드로 교체해주고 요청을 보낸다.
결과적으로 정리하면 retrofit2로 네트워크 요청을 보내고 okhttp3로 인증 헤더를 넣어서 사용하는 방식이다.
+ User 모델은 아래와 같이 data class로 작성하였다.
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
import java.util.*
@Parcelize
data class User(
var id: String,
var createdAt: Date,
var updatedAt: Date,
var username: String
) : Parcelable
'App > 개발' 카테고리의 다른 글
[안드로이드] 안드로이드에서 textView에 밑줄 긋는 방법 (0) | 2020.09.09 |
---|---|
[안드로이드] 카카오맵 코틀린 소스코드 저장 (0) | 2020.09.08 |
[안드로이드] 안드로이드 앱 프로가드 적용하는 방법 (0) | 2020.09.07 |
[안드로이드] SwipeRefreshLayout를 사용해서 레이아웃 리프레시하기 (0) | 2020.09.07 |
[안드로이드] AlertDialog와 ProgressBar를 이용해서 로딩 중 만들기 (0) | 2020.09.03 |