카테고리 없음
공공데이터를 이용한 앱 만들어보기(4) - DB에 넣어보기
카멜레온개발자
2021. 12. 1. 20:49
수신 받은 데이터를 DB에 한번 넣어보려고 한다
1. 화면은 다음과 같이 정리했다.
더보기
<?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"
android:orientation="vertical"
tools:context=".MainActivity" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btnRequest"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="요청하기" />
<Button
android:id="@+id/btnStationInsert"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="DB INSERT" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvStation"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
2. 버튼을 누르면
1) DB가 없으면 DB 생성(createDatabase 함수)
2) 테이블이 없으면 테이블 생성(createTable 함수)
3) 1개의 데이터만 요청한다. (총 갯수만 알아낼 목적으로 - RequestItemCount()함수)
더보기
Button btn2 = findViewById(R.id.btnStationInsert);
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
createDatabase(DATABASE_NAME); //데이터베이스 생성
createTable(); //테이블 생성
StringRequest request = new StringRequest(
Request.Method.GET,
"http://apis.data.go.kr/6260000/BusanBIMS/busStopList?serviceKey=___________&pageNo=1&numOfRows=1",
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
RequestItemCount(response);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "onErrorResponse : " + error.toString());
}
}
){
//요청 파라미터를 처리하는 메소드
@Nullable
@Override
protected Map<String, String> getParams() throws AuthFailureError {
//요청 객체가 하나 만들어짐
Map<String, String> params = new HashMap<String, String>();
//요청 큐에 넣어주면 된다
return super.getParams();
}
};
request.setShouldCache(false);
requestQueue.add(request);
}
});
public void createDatabase(String databaseName){
if(database == null){
try{
database = openOrCreateDatabase(databaseName, MODE_PRIVATE, null);
} catch (Exception e){
e.printStackTrace();
}
}
}
public void createTable(){
try{
if(database == null) return;
if(adapter == null) return;
String sql = "create table if not exists station "
+ "(bstopid INTEGER primary key, bstopnm varchar, arsno INTEGER, gpsx double, gpsy double, stoptype varchar, version INTEGER)";
database.execSQL(sql);
}
catch(Exception e){
e.printStackTrace();
}
}
3. 이 데이터의 경우 1개만 요청해도 총 갯수정보가 들어 있으므로 그 정보를 이용해서 모든 데이터를 다시 요청한다
('totalCount' 태그)
1) 총 데이터 갯수를 알아내고
2) 1000개씩 분할해서 요청한다(갯수는 조정가능)
더보기
private void RequestItemCount(String response)
{
int count = ParseStationCount(response);
int div = 1000;
int pages = count / div;
if(count % div > 0)
pages += 1;
RequestPage(pages, 1, div);
}
private int ParseStationCount(String response){
String curr_tag = "";
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput( new StringReader(response) );
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if(eventType == XmlPullParser.START_DOCUMENT) {
} else if(eventType == XmlPullParser.START_TAG) {
curr_tag = xpp.getName();
} else if(eventType == XmlPullParser.END_TAG) {
curr_tag = "";
} else if(eventType == XmlPullParser.TEXT) {
if(curr_tag.equals("totalCount"))
return Integer.parseInt(xpp.getText());
}
eventType = xpp.next();
}
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
4. 페이지별 요청은 다음과 같이 구현하고, DB에 insert한다
(DB insert시에는 낱개로 넣는것보다 Transaction을 이용하는 것이 빠른듯)
더보기
private void RequestPage(int total_page, int index_page, int div){
String requstStr = "http://apis.data.go.kr/6260000/BusanBIMS/busStopList?serviceKey=________________&pageNo="+index_page+"&numOfRows=" + div;
StringRequest request = new StringRequest(
Request.Method.GET,
requstStr,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
ArrayList<Station> list = ParseStatonStr(response);
insertData(list);
if(index_page + 1 <= total_page){
Log.d(TAG, "Progress : " + (index_page + 1) +"/" + total_page);
RequestPage(total_page, index_page + 1, div);
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
})
{
//요청 파라미터를 처리하는 메소드
@Nullable
@Override
protected Map<String, String> getParams() throws AuthFailureError {
//요청 객체가 하나 만들어짐
Map<String, String> params = new HashMap<String, String>();
//요청 큐에 넣어주면 된다
return super.getParams();
}
};
request.setShouldCache(false);
requestQueue.add(request);
}
public void insertData(ArrayList<Station> list){
try{
if(database == null) return;
if(adapter == null) return;
String sql = "";
String sql_insert = "insert or replace into station (bstopid, bstopnm, arsno, gpsx, gpsy, stoptype, version) values (";
Station station;
database.beginTransaction();
for(int i=0; i<list.size(); ++i)
{
sql = list.get(i).values() + ", 1)";
database.execSQL(sql_insert + sql);
}
database.setTransactionSuccessful();
}
catch(Exception e){
e.printStackTrace();
}
finally{
database.endTransaction();
}
}
5. 안드로이드 에뮬레이터를 실행시키고, 버튼을 누르면 다음과 같이 1000개씩 잘 얻어온다
6. 저장된 결과는 다음과같이 저장 가능하다
(안드로이드 스튜디오 Device Explorer > 아래 경로의 DB를 찾아가서 마우스 우클릭 > Save As 메뉴 선택 후 저장)
7. 저장된 파일을 Sqlite 뷰어 프로그램으로 열어보면 다음과 같이 나타난다