Retrofit이란?
OkHttp를 네트워크 계층으로 활용해서 구축한 RESTful HTTP통신 라이브러리 입니다.
AsncTask없이 백그라운드 스레드를 실행하며, Callback을 통해 메인스레드에서 UI를 업데이트하게 됩니다.
이후 안드로이드 스튜디오가 메인스레드에서 백그라운드 스레드를 실행하지 못하게 변경되면서
비동기 통신엔 결국 AsncTask를 사용하게 됩니다.
Retrofit의 장점
1. AsncTask와 비교해서 빠른 속도.
2. 어노테이션을 사용해 코드가 굉장히 직관적.
3. 간결한 코드로 재사용성 또한 높음
4. 구현히 굉장히 쉬움
Retrofit의 구성요소
1. DTO (Data Transfer Object)
- Bean이라고도 부릅니다. POJO를 사용하기도 합니다.
2. Interface
사용할 HTTP method를 정의해 둔 인터페이스가 필요합니다.
이후 인터페이스를 상속받아 통신 성공/실패시에 따른 작업을 직적 구현하면 됩니다.
3. Retrofit.Builder
Interface에 사용할 인스턴스 및 주소, Converter를 설정합니다.
Retrofit 사용준비
1. app수준 gradle에 dependencies추가를 합니다.
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation group: 'com.squareup.retrofit2', name: 'converter-gson', version: '2.3.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.6.4'
2. 매니페스트에 인터넷을 사용하기 위한 유저퍼미션을 추가합니다.
<uses-permission android:name="android.permission.INTERNET" />
이대로는 https는 접속할수 있지만, http는 접속이 불가능합니다. 필요하다면 아래의 추가작업을 확인해 주세요.
매니패스트의 어플리케이션 태그 안에 아래의 코드를 추가해 줍니다.
<application
//...생략
android:networkSecurityConfig="@xml/network_security_config"
//...생략
</application>
그리고 res폴더에 xml Resource Directory를 생성해 줍니다.
이후 생성된 XML Resource directory에 새 리소스 파일을 추가해줍니다.
이름은 network_security_config로 만듭니다.
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted = "true">
<trust-anchors>
<certificates src = "system"/>
</trust-anchors>
</base-config>
</network-security-config>
위의 작업을 마치면 안드로이드 어플리케이션에서 http에 접속할 수 있게 됩니다.
Retrofit 구현
1. DTO 생성
Bean을 적절한 어노테이션을 사용해 제작해 줍니다. 단, @SerializedName() 어노테이션은 필수입니다.
request의 결과로 받은 json데이터의 키값을 입력하면 retrofit이 gson converter를 통해 retrofit이 변수에 데이터를 넣어줍니다.
예시는 접은글을 통해 확인해 주세요.
package com.example.retrofittest;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class RetrfotBean {
@SerializedName("no")
@Expose
int no;
@SerializedName("name")
@Expose
String name;
@SerializedName("age")
@Expose
int age;
public RetrfotBean(int no, String name, int age) {
this.no = no;
this.name = name;
this.age = age;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
2. Inteerface 정의
사용할 메서드를 선언해 줍니다.
보통 어노테이션엔 HTTP method를 명시하고, 이어지는 소괄호에는 baseURL을 제외한 나머지 주소를 입력해줍니다.
<> 속엔 받을 타입을 선언해줍니다.
@GET("test/{jsp}")
Call<PostResult> getJspFile(@Path("jsp") String post);
위처럼 경로를 변수로 입력받을 수 있고,
@GET("Hair/Reservation/reservationListLoad.jsp?")
Call<String> getListString(@Query("userNo") String userNo);
위처럼 request로 보낼 값을 매개변수로 받을수도 있습니다.
@Multipart
@POST("reviewUpdate.jsp")
Call<String> insertReview(@PartMap Map<String, RequestBody> params,
@Part MultipartBody.Part files);
그리고 위처럼 Muitpart어노테이션으로 파일을 송신할수도 있습니다.
3. Retrofit.Builder
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.2.4:8080/")
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
Retrofit.Builder 의 인스턴스를 생성해 baseURL, Converterm Client를 설정합니다.
Converter는 여러개 등록가능하며 채에 거르듯 변환이 불가능하면 다음 컨버터를 확인하는 식입니다.
Gson은 변환이 불가능해도 가능하다고 반응한다고 하니, 마지막에 등록하는것이 좋습니다.
사용할때마다 빌더를 선언해줄수도 있지만, 보통은 자주 반복해서 사용하니
스태틱 메서드로 만들어서 그때마다 메서드만 호출하면 되게 구성할수 있습니다.
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
Retrofit2로 통신하기
이제 준비는 다 끝났으니 통신할 일만 남았습니다.
위에서 작업한 내용들을 조립해주면 됩니다.
1. 동기 통신하기
Call의 enqueue매서드를 사용해 동기통신을 하게 됩니다.
RetrofitService service = retrofit.create(RetrofitService.class);
Call<PostResult> call = service.getJspFile("retrofitTest.jsp");
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccessful()){
PostResult result = response.body();
Log.d(TAG, "onResponse:성공");
Log.d(TAG, "결과 : " + result);
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Log.d(TAG, "onResponse:실패");
Log.d(TAG, "결과 : " + t.);
}
});
2. 비동기 통신하기
전엔 call.execute().body()을 통해 간단히 작업할 수 있었습니다만,
현재 안드로이드는 메인스레드에서 백그라운드 스레드를 실행하지 못하기 떄문에 다른 방법을 한번 거쳐야 합니다.
AsyncTask가 deprecated가 되었기 때문에 대안으로 RxJAVA, Coroutine가 있습니다만...
Coroutine의 경우 코틀린으로 구현해야 하는데...음 이후에 추가로 작성하도록 하겠습니다.
public class getReviewList extends AsyncTask<Call, Void, String> {
//...
@Override
protected ReservationList doInBackground(Call... params) {
RetrofitService retrofitService = RetrofitCall.reservationService();
Call<ReservationList> call = retrofitService.getListForReviewByShop(shopNo);
try {
String result = call.execute().body();
Log.v(TAG, "result : " + result);
return result;
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
@Override
protected void onPostExecute(String result) {
}
...//
}
'IDE & Framework > Android' 카테고리의 다른 글
Android에서 SQLite 사용하기 (feat.ROOM) (0) | 2021.07.30 |
---|---|
AsyncTask는 왜 deprecated 되었을까? (0) | 2021.07.09 |
Recycler View item handeling (0) | 2021.06.21 |
Custom ListView 만들기(1/2) - 설계 (0) | 2021.06.05 |
LayoutInflater는 무엇일까? (0) | 2021.06.05 |