안드로이드

안드로이드 Retrofit2 사용 예제. GET, POST, PUT, PATCH, DELETE

알통몬_ 2018. 9. 13. 16:07
반응형



공감 및 댓글은 포스팅 하는데

 아주아주 큰 힘이 됩니다!!

포스팅 내용이 찾아주신 분들께 

도움이 되길 바라며

더 깔끔하고 좋은 포스팅을 

만들어 나가겠습니다^^

 


이번 포스팅에서는

Square, Inc. 에서 만들고 배포하고 있는 오픈 소스 라이브러리인

Retrofit2 에 대해 포스팅하려고 합니다.

Retrofit2 는 HTTP REST API 통신을 위한 라이브러리라고 하는데요.

https://square.github.io/retrofit/

A type-safe HTTP client for Android and Java

라고 나와있네요.


REST ,  GET, POST, PUT, PATCH, DELETE 가 궁금하신 분들은

https://spring.io/understanding/REST

요 사이트 들어가서 문서를 보시면 되겠습니다.


저는 안드로이드에서 사용할 거기 때문에

gradle을 추가해줬습니다.

2가지를 추가해주면 되는데요.

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0-rc02'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
}

2번째거는 data class <-> GSON으로 쉽게 변환해주는 거? 정도입니다 ㅎㅎ

그리고 당연히 인터넷이 되어야하니

manifest.xml 에 Internet 권한을 줍니다.

<uses-permission android:name="android.permission.INTERNET"/>

Retrofit2은 interface에 API를 정의하고, 이 인터페이스 클래스를 Retrofit2에

초기화 하는 과정을 거쳐서 사용하게 됩니다.


예제에 사용된 것들.

- Retrofit2 라이브러리

- JSON 형식의 REST API를 연습할 수 있는 예제 페이지

   http://jsonplaceholder.typicode.com

끝.


1. Data Class 만들기. 

코틀린을 섞어서 사용하면 Data Class 를 한줄의 코드로도 만들 수 있어서 좋습니다.

아래 둘 중 하나만 사용하시면 됩니다.

Data.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Data {
 
    private final int userId;
    private final int id;
    private final String title;
    private final String body;
 
    public Data(int userId, int id, String title, String body) {
        this.userId = userId;
        this.id = id;
        this.title = title;
        this.body = body;
    }
 
    public int getUserId() {
        return userId;
    }
 
    public int getId() {
        return id;
    }
 
    public String getTitle() {
        return title;
    }
 
    public String getBody() {
        return body;
    }
}
 
cs

Data.kt

1
2
data class Data(var userId : Int,
 var id : Int,
  var title : String,
 var body : String)
 
cs


2. API Service 정의하기.

RetrofitExService.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
public interface RetrofitExService {
 
    String URL = "http://jsonplaceholder.typicode.com";
 
    /**
     * GET 방식, URL/posts/{userId} 호출.
     * Data Type의 JSON을 통신을 통해 받음.
     * @Path("userId") String id : id 로 들어간 STring 값을, 첫 줄에 말한
     * {userId}에 넘겨줌.
     * userId에 1이 들어가면
     * "http://jsonplaceholder.typicode.com/posts/1" 이 최종 호출 주소.
     * @param userId 요청에 필요한 userId
     * @return Data 객체를 JSON 형태로 반환.
     */
    @GET("/posts/{userId}")
    Call<Data> getData(@Path("userId"String userId);
 
    /**
     * GET 방식, URL/posts/{userId} 호출.
     * Data Type의 여러 개의 JSON을 통신을 통해 받음.
     * @Query("userId") String id : getData와 다르게 뒤에 붙는 파라미터가 없음.
     * 방식은 위와 같음.
     * 단, 주소값이 "http://jsonplaceholder.typicode.com/posts?userId=1" 이 됨.
     * @param userId 요청에 필요한 userId
     * @return 다수의 Data 객체를 JSON 형태로 반환.
     */
    @GET("/posts")
    Call<List<Data>> getData2(@Query("userId"String userId);
 
 
    /**
     * POST 방식, 주소는 위들과 같음.
     * @FieldMap HashMap<String, Object> param :
     * Field 형식을 통해 넘겨주는 값들이 여러 개일 때 FieldMap을 사용함.
     * Retrofit에서는 Map 보다는 HashMap 권장.
     * @FormUrlEncoded Field 형식 사용 시 Form이 Encoding 되어야 하기 때문에 사용하는 어노테이션
     * Field 형식은 POST 방식에서만 사용가능.
     * @param param 요청에 필요한 값들.
     * @return Data 객체를 JSON 형태로 반환.
     */
    @FormUrlEncoded
    @POST("/posts")
    Call<Data> postData(@FieldMap HashMap<String, Object> param);
 
 
    /**
     * PUT 방식. 값은 위들과 같음.
     * @Body Data param : 통신을 통해 전달하는 값이 특정 JSON 형식일 경우
     * 매번 JSON 으로 변환하지 않고, 객체를 통해서 넘겨주는 방식.
     * PUT 뿐만 아니라 다른 방식에서도 사용가능.
     * @param param 전달 데이터
     * @return Data 객체를 JSON 형태로 반환.
     */
    @PUT("/posts/1")
    Call<Data> putData(@Body Data param);
 
 
    /**
     * PATCH 방식. 값은 위들과 같습니다.
     * @FIeld("title") String title : patch 방식을 통해 title 에 해당하는 값을 넘기기 위해 사용.
     * @FormUrlEncoded Field 형식 사용 시 Form이 Encoding 되어야 하기 때문에 사용하는 어노테이션
     * @param title
     * @return
     */
    @FormUrlEncoded
    @PATCH("/posts/1")
    Call<Data> patchData(@Field("title"String title);
 
 
    /**
     * DELETE 방식. 값은 위들과 같습니다.
     * Call<ResponseBody> : ResponseBody는 통신을 통해 되돌려 받는 값이 없을 경우 사용.
     * @return
     */
    @DELETE("/posts/1")
    Call<ResponseBody> deleteData();
 
    /*
     * DELETE 방식에서 @Body를 사용하기 위해서는 아래처럼 해야함.
     * @HTTP(method = "DELETE", path = "/Arahant/Modification/Profile/Image/User", hasBody = true)
     * Call<ResponseBody> delete(@Body RequestGet parameters);
     */
 
}
 
cs


GET, POST, PUT, PATCH, DELETE 모두 정의해 놓았습니다.

주석도 달아 놓았으니, 이해하시는데는 크게 무리가 없지 않을까 싶습니다.


3. 샘플 페이지에 요청을 보내서 실제로 통신해보기.

MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package com.example.rowan_dev.retrofit2ex;
 
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
 
import java.util.HashMap;
import java.util.List;
 
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
 
public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(RetrofitExService.URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        RetrofitExService retrofitExService = retrofit.create(RetrofitExService.class);
        retrofitExService.getData("1").enqueue(new Callback<Data>() {
            @Override
            public void onResponse(@NonNull Call<Data> call, @NonNull Response<Data> response) {
                if (response.isSuccessful()) {
                    Data body = response.body();
                    if (body != null) {
                        Log.d("data.getUserId()", body.getUserId() + "");
                        Log.d("data.getId()", body.getId() + "");
                        Log.d("data.getTitle()", body.getTitle());
                        Log.d("data.getBody()", body.getBody());
                        Log.e("getData end""======================================");
                    }
                }
            }
 
            @Override
            public void onFailure(@NonNull Call<Data> call, @NonNull Throwable t) {
 
            }
        });
 
        retrofitExService.getData2("1").enqueue(new Callback<List<Data>>() {
            @Override
            public void onResponse(@NonNull Call<List<Data>> call, @NonNull Response<List<Data>> response) {
                if (response.isSuccessful()) {
                    List<Data> datas = response.body();
                    if (datas != null) {
                        for (int i = 0; i < datas.size(); i++) {
                            Log.e("data" + i, datas.get(i).getUserId() + "");
                        }
                        Log.e("getData2 end""======================================");
                    }
                }
            }
 
            @Override
            public void onFailure(@NonNull Call<List<Data>> call, @NonNull Throwable t) {
 
            }
        });
 
        HashMap<String, Object> input = new HashMap<>();
        input.put("userId"1);
        input.put("title""this is title!!");
        input.put("body""this is body!");
        retrofitExService.postData(input).enqueue(new Callback<Data>() {
            @Override
            public void onResponse(@NonNull Call<Data> call, @NonNull Response<Data> response) {
                if (response.isSuccessful()) {
                    Data body = response.body();
                    if (body != null) {
                        Log.d("data.getUserId()", body.getUserId() + "");
                        Log.d("data.getId()", body.getId() + "");
                        Log.d("data.getTitle()", body.getTitle()+"");
                        Log.d("data.getBody()", body.getBody()+"");
                        Log.e("postData end""======================================");
                    }
                }
            }
 
            @Override
            public void onFailure(@NonNull Call<Data> call, @NonNull Throwable t) {
 
            }
        });
 
        retrofitExService.putData(new Data(11"title""body")).enqueue(new Callback<Data>() {
            @Override
            public void onResponse(@NonNull Call<Data> call, @NonNull Response<Data> response) {
                if (response.isSuccessful()) {
                    Data body = response.body();
                    if (body != null) {
                        Log.d("data.getUserId()", body.getUserId() + "");
                        Log.d("data.getId()", body.getId() + "");
                        Log.d("data.getTitle()", body.getTitle());
                        Log.d("data.getBody()", body.getBody());
                        Log.e("putData end""======================================");
                    }
                }
            }
 
            @Override
            public void onFailure(@NonNull Call<Data> call, @NonNull Throwable t) {
 
            }
        });
 
        retrofitExService.patchData("1").enqueue(new Callback<Data>() {
            @Override
            public void onResponse(@NonNull Call<Data> call, @NonNull Response<Data> response) {
                if (response.isSuccessful()) {
                    Data body = response.body();
                    if (body != null) {
                        Log.d("data.getUserId()", body.getUserId() + "");
                        Log.d("data.getId()", body.getId() + "");
                        Log.d("data.getTitle()", body.getTitle());
                        Log.d("data.getBody()", body.getBody());
                        Log.e("patchData end""======================================");
                    }
                }
            }
 
            @Override
            public void onFailure(@NonNull Call<Data> call, @NonNull Throwable t) {
 
            }
        });
 
        retrofitExService.deleteData().enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                if (response.isSuccessful()) {
                    ResponseBody body = response.body();
                    if (body != null) {
                        Log.d("body", body.toString() + "");
                        Log.e("patchData end""======================================");
                    }
                }
            }
 
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
 
            }
        });
    }
}
 
cs


포스팅에 올린 프로젝트는 깃허브에 공유해 놓았습니다.

https://github.com/Parksunggyun/Retrofit2Ex

다음 번에는 

스프링 or Java Vertx Http Server 와 통신하는 예제를 올려보도록 하겠습니다.

이상입니다. 감사합니다.


반응형