Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
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
Tags
more
Archives
Today
Total
관리 메뉴

기록장

[안드로이드] Volley(볼리) 통신 / RequestQueue 본문

안드로이드

[안드로이드] Volley(볼리) 통신 / RequestQueue

edit0 2021. 1. 9. 19:42

앞서 포스팅에선 HttpURLConnection 객체를 사용하여 웹서버와 통신하였다. 전체적으로 호출, 응답, 스레드 등등 코드 길이가 길어지고 핸들러도 다룰줄 알아야 한다. 그래서 조금 더 간단하게 사용하기 위해 여러 라이브러리가 나왔고 그 중에서 Volley 라이브러리를 구현해보도록 하겠다.

 

Volley요청 객체를 만들고 이 요청 객체를 요청 큐에 넣어주면 된다. 그 다음은 알아서 웹서버에 요청하고 응답까지 받아준다. 사용자는 응답을 받을 수 있도록 지정된 메소드를 만들어주면 응답이 왔을 때 이 메소드가 자동으로 호출되므로 사용하면 된다. 그리고 쓰레드 관리를 안해줘도 되서 메인 쓰레드로 UI 접근이 편한다. 사용 시 add(추가)만 해주면 된다.

 

Volley의 몇가지 장점

  • 네트워크 요청(Request) 우선 순위를 자동으로 관리한다.
  • 동시에 여러 네트워크 요청을 할 수 있다.
  • 요청을 할 때 Cache 적용 여부를 의식하지 않아도 된다.
  • RequestQueue 객체를 한 번만 선언하여 사용 가능

* 이 글은 영화진행위원회 오픈 API를 사용하였음

www.kobis.or.kr/kobisopenapi/homepg/main/main.do

 

영화진흥위원회 오픈API

OPEN API 서비스 영화진흥위원회 영화관입장권통합전산망에서 제공하는 오픈API 서비스로 더욱 풍요롭고 편안한 영화 서비스를 즐겨보세요.

www.kobis.or.kr

 

Volley 라이브러리를 사용하기 위해서는 dependencies를 추가해줘야한다.

implementation 'com.android.volley:volley:1.1.0'

 

네트워크 보안 구성 파일 추가

 

res -> xml -> network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true"/>
</network-security-config>

그 다음

AndroidManifest.xml 내 application에 아래 구문 추가

android:networkSecurityConfig="@xml/network_security_config"

보안 관련 자세한 내용은 아래 참조

https://developer.android.com/training/articles/security-config?hl=ko

 

네트워크 보안 구성  |  Android 개발자  |  Android Developers

앱 개발자가 안전한 구성 파일에서 네트워크 보안 설정을 사용자설정할 수 있는 기능입니다.

developer.android.com

 

코드

 

activity_main.xml

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

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/edittext1"
        android:inputType="textPersonName"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/button1"
        android:text="요청하기"/>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/textview1"
                android:textSize="20dp"/>

        </LinearLayout>
    </ScrollView>

</LinearLayout>

 

MainActivity.java

public class MainActivity extends AppCompatActivity {

    EditText et1;
    Button b1;
    TextView tv1;

    static RequestQueue requestQueue;

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

        et1 = findViewById(R.id.edittext1);
        b1 = findViewById(R.id.button1);
        tv1 = findViewById(R.id.textview1);

        b1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                request();
            }
        });

        //최초 한 번만 생성하기 위해 최초 null일 경우만 생성
        if(requestQueue == null)
            //getApplicationContext() 메소드를 통해 Context 객체를 전달
            requestQueue = Volley.newRequestQueue(getApplicationContext());
    }

    public void request(){
        String url = et1.getText().toString();

        //요청을 위한 Request 객체 생성
        //파라미터 (통신 방식 get, 요청할 url, String으로 응답 받겠음)
        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());
            }
        }) { //post 방식으로 파라미터를 넣고 싶을 경우, Request 객체 안에 메소드를 재정의
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();

                //데이터 보낼 경우 put 사용
                /*String value = "Value";
                params.put("key",value);*/

                return params;
            }
        };

        request.setShouldCache(false); //캐시 데이터 false, 이전 데이터가 있으면 다시 보여줄 수 있으므로 항상 새로 받은 데이터 보여주기 위해 false
        requestQueue.add(request); //RequestQueue에 추가

        println("요청 보냄.");
    }

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

 

결과

 

 

+ 응용해보기

 

이전 포스팅 HttpURLConnection에서는 json 파일의 데이터를 뽑아서 보여주고 싶은 데이터들만 보여주었다.

이번에는 영화 제목을 입력하면 그에 대한 정보가 나오도록 만들어보도록 하겠다.

 

json 파일

 

activity_main.xml은 위와 동일

 

MainActivity.java

public class MainActivity extends AppCompatActivity {

    EditText et1;
    Button b1;
    TextView tv1;

    static RequestQueue requestQueue;

    String search = "";
    ArrayList<MainActivity_list> main_list_array = new ArrayList<>();

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

        et1 = findViewById(R.id.edittext1);
        b1 = findViewById(R.id.button1);
        tv1 = findViewById(R.id.textview1);

        b1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                search = et1.getText().toString();

                for(int i=0;i<main_list_array.size();i++){
                    if(main_list_array.get(i).getlist_data2().equals(search)) {
                        tv1.append("Rank: " + main_list_array.get(i).getlist_data1() + "\nMovie Name: " + main_list_array.get(i).getlist_data2() + "\nOpen date: " +
                                main_list_array.get(i).getlist_data3() + "\n");

                    }
                }
            }
        });

        //최초 한 번만 생성하기 위해 최초 null일 경우만 생성
        if(requestQueue == null)
            //getApplicationContext() 메소드를 통해 Context 객체를 전달
            requestQueue = Volley.newRequestQueue(getApplicationContext());

        request();
    }

    public void request(){
        String url = "http://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=인증키&targetDt=20120101";

        //요청을 위한 Request 객체 생성
        //파라미터 (통신 방식 get, 요청할 url, String으로 응답 받겠음)
        StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                //정상 응답일 경우 실행
                try {
                    JSONObject jsonObject = new JSONObject(response);
                    JSONObject jsonObject2 = jsonObject.getJSONObject("boxOfficeResult");

                    JSONArray jsonArray = jsonObject2.getJSONArray("dailyBoxOfficeList");

                    //배열 길이만큼 반복
                    for(int i=0;i<jsonArray.length();i++){

                        JSONObject item = jsonArray.getJSONObject(i); //getJSONObject 메소드는 json배열을 JSONObject 객체로 만듬

                        //key 값을 가져와서 각각의 String 변수에 넣어줌
                        String get_rank = item.getString("rank");
                        String get_movieNm = item.getString("movieNm");
                        String get_openDt = item.getString("openDt");

                        //MainActivity_list 클래스의 객체 생성 후 set 후
                        //MainActivity_lsit의 ArrayList에 add 해줌
                        //각 객체 변수 하나당 한사이클의 데이터 값들이 들어있다는 것
                        MainActivity_list main_list = new MainActivity_list();

                        main_list.setlist_data1(get_rank);
                        main_list.setlist_data2(get_movieNm);
                        main_list.setlist_data3(get_openDt);

                        main_list_array.add(main_list);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }


            }}, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                //에러 발생 시 실행
                tv1.append("에러 -> " + error.getMessage());
            }
        }) { //post 방식으로 파라미터를 넣고 싶을 경우, Request 객체 안에 메소드를 재정의
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();

                //데이터 보낼 경우 put 사용
                //String value = "Value";
                //params.put("key",value);

                return params;
            }
        };

        request.setShouldCache(false); //캐시 데이터 false, 이전 데이터가 있으면 다시 보여줄 수 있으므로 항상 새로 받은 데이터 보여주기 위해 false
        requestQueue.add(request); //RequestQueue에 추가

    }
}

 

결과

 

실행 시 아무것도 안나올 것이다. 당연하지만, 영화 정보를 웹서버에서 가져오고 안보여줬기 때문이다..

EditText 안에 영화 제목을 넣어줘야 한다.

 

다음, 영화 제목 입력

 

요청 -> 결과 확인

 

 

부족한 점, 피드백 환영합니다.

 

감사합니다.

 

 

참고

정재곤, 『Do it! 안드로이드 앱 프로그래밍 - 개정 6판』, 이지스퍼블리싱(주)