기록장
[안드로이드] Volley(볼리) 통신 / RequestQueue 본문
앞서 포스팅에선 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판』, 이지스퍼블리싱(주)
'안드로이드' 카테고리의 다른 글
[안드로이드] RecyclerView(리사이클러뷰) (0) | 2021.01.12 |
---|---|
[안드로이드] ListView(리스트뷰) (0) | 2021.01.12 |
[안드로이드] 웹, HTTP 통신, 공공데이터 API, JSON 파일 데이터 가져오기 / HttpURLConnection, JSON Parsing(제이슨 파싱), 공공데이터포털 (0) | 2021.01.08 |
[안드로이드] 네트워킹, Socket (소켓) (0) | 2021.01.07 |
[안드로이드] AsyncTask 이해 및 간단한 예제 (0) | 2021.01.07 |