Kotlin + Retrofit (POST Method)

TPark·2019년 11월 22일
0

안드로이드

목록 보기
1/10
post-custom-banner

오늘은 Retrofit을 통해 API와 통신하는 기능을 구현해봤습니다. 요즘 CometChat이라는 API를 이용해서 간단한 채팅앱을 구현하는 중인데 아이디로 친구추가하는 기능을 REST API와 통신하는 방식으로 구현하게 되서 이번 포스트를 작성하게 되었습니다.

우선 build.gradle(Module:app) 파일에 다음 dependencies를 추가해줍니다.

implementation 'com.squareup.retrofit2:retrofit:(insert latest version)'
implementation 'com.squareup.retrofit2:converter-gson:(insert latest version)'

그 다음 HTTP API를 interface 형태로 만들어 줍니다.

interface CometChatFriendsService {
        @Headers("accept: application/json",
                        "content-type: application/json")
        @POST("{version}/users/{uid}/friends")
        fun addFriend(@Header("apikey") apiKey: String,
                      @Header("appid") appID: String,
                      @Body params: HashMap<String, List<String>>,
                      @Path("version") version: String,
                      @Path("uid") uid: String)
                : Call<Data>
}

맨 위에 @Headers에는 정적 헤더들을 명시해줍니다.

모든 메소드들은 반드시 상대 URL과 요청 메소드를 명시하는 어노테이션을 가지고 있어야합니다. 전 Post 메소드가 필요해서 @POST를 사용했는데 다른 메소드가 필요하신 분들은 @GET, @DELETE 등으로 대체해서 사용하시면 됩니다.

요청 URL은 동적으로 부분치환이 가능한데, {}안에 있는 부분은 메소드의 매개변수에 명시된 @Path로 변경이 가능합니다.

요청 메소드인 addFriend의 매개변수에는 동적인 헤더를 명시하는 @Header, 해당 POST 메소드에서 요구하는 정보를 담고 있는 @Body, URL의 부분치환할 부분을 담고 있는 @Path 어노테이션이 있습니다.

참고로 헤더를 모든 요청마다 추가하셔야 한다면 OkHttp interceptor 사용을 권장합니다.

위의 요청 메소드를 Talend API Tester로 만들면 이런 모습이 되겠네요.

image.png

제가 이 요청을 통해 받을 데이터는 아래와 같은 형태인데요.

"data":{
	"accepted":{
		"superhero3":{
			"success": true,
			"message": "Updated relationship status to accepted."
		},
		"superhero4":{
			"success": true,
			"message": "Updated relationship status to accepted."
		}
	}
}

이 데이터를 파싱하기 위한 data class들을 만들겠습니다.

data class Data(val data: Accepted)
data class Accepted(val accepted: HashMap<String, Friend>)
data class Friend(val success: Boolean, val message: String)

그 다음 Retrofit 객체를 생성해주고 생성한 객체를 통해 아까 만든 interface를 구현하여 생성해줍니다. 그리고 Body에 넣을 데이터를 HashMap형태로 만들어준뒤 서비스의 addFriend 메소드를 불러줍니다.

        //Retrofit 객체 생성
        val retrofit = Retrofit.Builder()
            .baseUrl(this.URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        //retrofit 객체를 통해 인터페이스 생성
        val service = retrofit.create(CometChatFriendsService::class.java)

        //Body에 담을 데이터 생성
        val friends = ArrayList<String>()
        friends.add(friendID)
        val body = HashMap<String, List<String>>()
        body.put("accepted", friends)
        
        service.addFriend(context.getString(R.string.apiKey), context.getString(R.string.appID),
            body, version, uid)?.enqueue(object : Callback<Data> {
            override fun onFailure(call: Call<Data>, t: Throwable) {
                Log.d("CometChatAPI::", "Failed API call with call: " + call +
                        " + exception: " + t)
            }

            override fun onResponse(call: Call<Data>, response: Response<Data>) {
                Log.d("Response:: ", response.body().toString())
                val friends = response.body()!!.data.accepted

                Log.d("Friends:: ", friends.toString())
                for (friendName in friends.keys) {
                    Log.d("${friendName}:: ", friends[friendName].toString())
                }

            }
        })

위 코드를 실행한뒤 로그캣을 확인해보니 아래와 같은 응답을 받을수 있네요.

D/Response::: Data(data=Accepted(accepted={superhero3=Friend(success=true, message=Updated relationship status to accepted.)}))
D/Friends::: {superhero3=Friend(success=true, message=Updated relationship status to accepted.)}
D/superhero3::: Friend(success=true, message=Updated relationship status to accepted.)

끝으로 네트워킹을 하기 때문에 Manifest파일에 인터넷 사용 퍼미션을 추가하는 것도 잊으시면 안됩니다.

post-custom-banner

3개의 댓글

comment-user-thumbnail
2020년 3월 6일

제가 Kotlin 관련 글을 찾다가 벨로그로 돌아올줄이야..! ㅋㅋㅋ
저도 개발하면서 배운것들을 좀 정리해야겠습니다 .

잘 읽고가요~

답글 달기