공감 및 댓글은 포스팅 하는데 아주아주 큰 힘이 됩니다!! 포스팅 내용이 찾아주신 분들께 도움이 되길 바라며 더 깔끔하고 좋은 포스팅을 만들어 나가겠습니다^^
|
이번 포스팅에서는
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 |
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(1, 1, "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 와 통신하는 예제를 올려보도록 하겠습니다.
이상입니다. 감사합니다.
'안드로이드' 카테고리의 다른 글
안드로이드 screen size 스크린 사이즈, 화면 크기 구하는 코드 (0) | 2018.10.17 |
---|---|
안드로이드 스튜디오에서 람다식 사용하려면? (0) | 2018.10.02 |
안드로이드 TabLayout tab 갤럭시 탭에서 같은 사이즈로 나오게 하는 방법 (0) | 2018.09.11 |
CoordinatorLayout, AppBarLayout, CollapsingToolbarLayout, RecyclerView 등을 사용한 머터리얼 디자인 레이아웃 (0) | 2018.09.06 |
안드로이드 스플래시화면 만들기 without layout xml (0) | 2018.09.05 |