유혁의 개발 스토리

[Android] Retrofit2 를 이용한 통신방식 본문

Android

[Android] Retrofit2 를 이용한 통신방식

유혁. 2018. 2. 7. 16:56

 

 

1. Retrofit2란 무엇인가?

 

Retrofit은 Square사에서 제공하는 오픈소스 라이브러리 입니다. (안드로이드 서버와 통신방식 중 하나 이전 HttpClient, HttpURLConnection, okhttp)

REST API와의 인터페이스를 위한 자신만의 Type-Safe HTTP 라이브러리를 개발하는것은 정말 고통스러울 수 있습니다. Connection 만들기, 캐싱, 실패한 요청 다시 시도, 스레딩, Response 파싱, 에러 핸들링등과 같은 많은 기능을 처리해야합니다. 반면, Retrofit은 매우 좋은 설계가 되어있고 문서화, 테스트가 되어있어 귀중한 시간과 고통을 줄여주는 검증 된 라이브러리입니다.

 

 

 

2. Retrofit2 예제

 

- 1. gradle 파일에

 

compile 'com.squareup.retrofit2:retrofit:2.1.0'

compile 'com.squareup.retrofit2:converter-gson:2.1.0'

 

라이브러리를 추가해줍니다.

 

 

- 2. manifest.xml 에 Internet 사용 권한을 부여합니다.

 

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

 

인터넷 통신을 하려면 인터넷사용 권한이 당연히 필요하겠죠?

 

 

 

- 3. 모델 클래스 생성

 

Contributor.java

 

public class Contributor {

    String login;
    String html_url;

    int contributions;

    @Override
    public String toString() {
        return login + " (" + contributions + ")";
    }
}

 

- 4. 인터페이스 생성

 

GitHubService.java

public interface GitHubService {
  @GET(repos/{owner}/{repo}/contributors)
  Call<List<Contributor>> repoContributors(
      @Path(owner) String owner,
      @Path(repo) String repo);
}

 

- 5. HTTP 호출(동기)

 

MainActivity.java

GitHubService gitHubService = GitHubService.retrofit.create(GitHubService.class);
Call<List<Contributor>> call = gitHubService.repoContributors(square, retrofit);
List<Contributor> result = call.execute().body();

기본적으로 생성된 부분  onCreate 내에 선언해줍니다.

 

- 6. activity_main.xml

<Button
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="Fetch"
  android:id="@+id/button"
  android:layout_alignParentBottom="true"
  android:layout_centerHorizontal="true"
  android:layout_marginBottom="151dp" />

<TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:textAppearance="?android:attr/textAppearanceLarge"
  android:text=""
  android:id="@+id/textView"
  android:layout_above="@+id/button"
  android:layout_alignParentEnd="true"
  android:layout_alignParentStart="true"
  android:layout_alignParentTop="true"
  android:textIsSelectable="false" />

 

- 7. 버튼을 이용해 HTTP동기호출을 하여야 하기에 다음과 같이 코드를 작성합니다.

 

Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {
    GitHubService gitHubService = GitHubService.retrofit.create(GitHubService.class);
    Call<List<Contributor>> call = gitHubService.repoContributors(square, retrofit);
    String result = call.execute().body().toString();
    TextView textView = (TextView) findViewById(R.id.textView);
    textView.setText(result);
  }
});

 

- 8. 위 소스는 작동하지 않습니다. 안드로이드는 UI Thread에서 네트워크 호출을 허용하지 않습니다. 그래서 이전 통신방식도 AysncTask를 사용했던 겁니다.

 

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
GitHubService gitHubService = GitHubService.retrofit.create(GitHubService.class);
final Call<List<Contributor>> call = gitHubService.repoContributors("square", "retrofit");
new NetworkCall().execute(call);
}
});


}
private class NetworkCall extends AsyncTask<Call, Void, String> {

@Override
protected String doInBackground(Call[] params) {
try {
Call<List<Contributor>> call = params[0];
Response<List<Contributor>> response = call.execute();
return response.body().toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

@Override
protected void onPostExecute(String result) {
final TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(result);
}
}
}

이렇게 바꿔줍니다.

 

 

 

** 비동기방식

GitHubService gitHubService = GitHubService.retrofit.create(GitHubService.class);
Call<List<Contributor>> call = gitHubService.repoContributors("square", "retrofit");
call.enqueue(new Callback<List<Contributor>>() {
@Override
public void onResponse(Call<List<Contributor>> call,
Response<List<Contributor>> response) {

TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(response.body().toString());
}

@Override
public void onFailure(Call<List<Contributor>> call, Throwable t) {

}
});

비동기 방식은 Button이랑 클릭 리스너 생성 필요없습니다. 그냥 선언과동시에 백그라운드 처리합니다.

 

 

- 9. activity_main.xml 수정

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text=""
android:id="@+id/textView"
android:layout_above="@+id/button"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:textIsSelectable="false" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fetch"
android:id="@+id/button"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="151dp" />
</LinearLayout>

이렇게 수정해줍니다. View는 예제소스가 틀이 없어서 제가만든거 사용하세요.

 

 

- 10. 결과

 

 

 

 

+ Post방식

 

Retrofit은 Restful api와 잘맞습니다.

인터페이스에서 GET, POST, PUT, DELETE 방식으로 선언이 쉽습니다.

 

Restful API 테스트 서버를 열고싶었으나 시간이 많이 소요될것 같아.

간단하게 테스트 하였습니다.

 

 

Service부분에서

 

@GET("repos/{owner}/{repo}/contributors")
Call<List<Contributor>> repoContributors(
@Path("owner") String owner
, @Path("repo") String repo)
;

@FormUrlEncoded
@POST("token")
Call<Test> createUser(@Field("token") String token);

밑 @POST부분을 추가하여 특정 값을 서버쪽으로 넘겨주는 메소드입니다.

 

GitHubService gitHubService = GitHubService.retrofit.create(GitHubService.class);
final Call<Test> call = gitHubService.createUser("token");
call.enqueue(new Callback<Test>() {
@Override
public void onResponse(Call<Test> call, Response<Test> response) {
// 성공
}

@Override
public void onFailure(Call<Test> call, Throwable t) {
// 실패
}
});

 

비동기 부분의 소스입니다.

.createUser("넘기고싶은 값");

선언하여 비동기식으로 넘겨주면

 

http://특정 서버 URL/../../token

 

에게 입력한 값을 Key값 token으로 Value값 "넘기고싶은 값" 으로 전달해줍니다.

 

@Query , @BODY 등등 있으나 생략하겠습니다.

http://devflow.github.io/retrofit-kr/

 

이곳 참조하세요.

 

 

 

 

 

 

 

3. 동기 비동기 방식 차이

 

동기(synchronous) : 요청과 동시에 결과가 나타남. 특정함수를 선언하여 결과값을 즉시 return 받는방식

 

비동기(Aysnchronous) : 요청과 동시에 결과가 나타나지 않음. 사용자는 요청을 하고 제어권을 다시 가짐. 간단하게 설명하면 요구 프로세스를 백그라운드에서 처리한다라고 이해하시면 됩니다.

 

 

 

 

참조

https://academy.realm.io/kr/posts/retrofit2-for-http-requests/   

https://code.tutsplus.com/tutorials/getting-started-with-retrofit-2--cms-27792

http://devuryu.tistory.com/44