Kotlin + Retrofit (POST Method)

TPark·2019년 11월 22일
0

안드로이드

목록 보기
1/10

오늘은 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로 만들면 이런 모습이 되겠네요.

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

"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파일에 인터넷 사용 퍼미션을 추가하는 것도 잊으시면 안됩니다.

3개의 댓글

comment-user-thumbnail
2020년 3월 6일

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

잘 읽고가요~

답글 달기