Android - Volley 사용

유의선·2023년 7월 29일
0

웹 서버에 요청하고 응답을 받을 때는 HttpURLConnection 객체를 사용할 수 있지만 요청과 응답에 필요한 코드의 양이 많다. 그리고 스레드를 사용하면서 넣어야 하는 코드의 양도 많다.
이런 문제를 해결하기 위한 라이브러리들이 있는데, 그 중 하나가 Volley다.

Volley 라이브러리는 웹 요청과 응답을 단순화하기 위해 만들어진 라이브러리다.
Volley를 사용하려면 먼저 요청(Request) 객체를 만들고 이 객체를 요청 큐(RequestQueue)라는 곳에 넣어주기만 하면 된다.
그러면 요청 큐가 알아서 웹 서버에 요청하고 응답까지 받아준다. 응답을 받을 수 있도록 지정된 메소드를 만들어두기만 하면 응답이 왔을 때 그 메소드가 자동으로 호출된다.

Volley 라이브러리이 가장 큰 장점은 스레드를 신경쓰지 않아도 된다는 점이다.
요청 큐가 내부에서 스레드를 만들어 웹 서버에 요청하고 응답하는 과정을 진행하는데, 응답을 처리할 수 있는 메소드를 호출할 때는 메인 스레드에서 처리할 수 있도록 만들기 때문이다.
따라서 스레드를 사용할 필요도 없고, 화면에 결과를 표시할 때 핸들러를 사용할 필요도 없다.


Volley를 사용해서 웹 요청과 응답 처리하기

Volley는 외부 라이브러리이므로 build.gradle 파일에 라이브러리 정보를 추가한다

dependencies {

    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.6.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

    implementation 'com.android.volley:volley:1.2.0'
}

AndroidManifest.xml 파일에 INTERNET 권한을 추가하고
application 태그에 usesCleartextTraffic 속성을 추가한다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.techtown.request">
    
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:usesCleartextTraffic="true"

activity_main.xml 레이아웃에 입력상자와 버튼, 스크롤뷰와 그 안에 텍스트뷰를 추가하였다.


MainActivity.java 파일에 코드를 작성하였다.

public class MainActivity extends AppCompatActivity {
    EditText editText;
    TextView textView;

    static RequestQueue requestQueue;

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

        editText = findViewById(R.id.editText);
        textView = findViewById(R.id.textView);

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                makeRequest();
            }
        });

        if(requestQueue == null){
            requestQueue = Volley.newRequestQueue(getApplicationContext());
        }
    }

    public void makeRequest() {
        String url = editText.getText().toString();

        StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                println("응답 -> " + response);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                println("에러 -> " + error.getMessage());
            }
        }) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();

                return params;
            }
        };

        request.setShouldCache(false);
        requestQueue.add(request);
        println("요청 보냄");
    }

    public void println(String data) {
        textView.append(data + "\n");
    }
}

요청 큐를 선언하고 객체를 생성하였다.

public class MainActivity extends AppCompatActivity {
    
    ...

    static RequestQueue requestQueue;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

		...

        if(requestQueue == null){
            requestQueue = Volley.newRequestQueue(getApplicationContext());
        }
    }

요청 큐는 한 번만 만들어 계속 사용할 수 있기 때문에 static 키워드로 클래스 변수를 선언한 후 할당하였다.
요청 큐를 만들 때는 Volley.newRequestQueue 메소드를 사용하였다.


텍스트뷰에 문자를 출력하는 메소드 println을 정의하였다.

    public void println(String data) {
        textView.append(data + "\n");
    }

이번에는 스레드를 사용하지 않으므로 핸들러로 정의할 필요가 없었다.


웹 서버에 요청을 보내고 결과를 받는 메소드 request를 정의하였다.

    public void makeRequest() {
        String url = editText.getText().toString();

        StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                println("응답 -> " + response);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                println("에러 -> " + error.getMessage());
            }
        }) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();

                return params;
            }
        };

        request.setShouldCache(false);
        requestQueue.add(request);
        println("요청 보냄");
    }

요청 객체를 StringRequest 클래스로 만들었다.

        StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                println("응답 -> " + response);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                println("에러 -> " + error.getMessage());
            }
        }) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();

                return params;
            }
        };

요청 객체를 new 연산자로 만들 때 네 개의 파라미터를 전달하였다.

첫 번째 파라미터로는 GET 또는 POST 메소드를 전달하여 요청 방식을 지정한다.
두 번째 파라미터로는 웹 사이트 주소를 전달한다.
세 번째 파라미터로는 응답받을 리스너 객체를 전달한다. 이 리스너의 onResponse 메소드는 응답을 받았을 때 자동으로 호출된다.
네 번째 파라미터로는 에러가 발생했을 때 호출될 리스너 객체를 전달한다.
여기서는 전달 방식으로 GET 방식을 사용했지만 POST 방식을 사용하면서 요청 파라미터를 전달하고자 한다면 getParams 메소드에서 반환하는 HashMap 객체에 파라미터 값들을 넣어주면 된다.

요청 객체를 만들었다면 이 객체를 요청 큐에 넣어준다.

        request.setShouldCache(false);
        requestQueue.add(request);
        println("요청 보냄");

요청 큐의 add 메소드로 요청 객체를 넣으면 요청 큐가 자동으로 요청과 응답 과정을 진행한다.
요청 객체는 cache 메커니즘을 지원하는데 이전 응답 결과를 사용하지 않겠다면 setShouldCache 메소드를 사용해 cache를 사용하지 않도록 설정할 수 있다.


버튼을 누르면 정의한 요청 메소드가 실행되도록 하였다.

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                makeRequest();
            }
        });

0개의 댓글