2023.02.27 - 안드로이드 앱개발자 과정

CHA·2023년 2월 27일
0

Android



Open API


Open API 란?

Open API 를 알아보기 이전에 API(Application Programming Interface) 가 무엇인지 부터 알아봅시다. API란 정의 및 프로토콜 집합을 사용하여 두 소프트웨어 구성 요소가 서로 통신할 수 있게 하는 메커니즘입니다. 예를 들어, 기상청의 소프트웨어 시스템에는 일일 기상 데이터가 들어 있습니다. 휴대폰의 날씨 앱은 API를 통해 기상청의 시스템과 ‘대화’하여 휴대폰에 매일 최신 날씨 정보를 표시할 수 있게됩니다.

Open API 도 말 그대로 Open 된 API 입니다. 여러 사람이 공동으로 사용할 필요가 있는 자원에 대해 사용자들이 자원에 대한 전문적인 지식이 없어도 쉽게 사용할 수 있도록 도와주는 인터페이스죠. 이러한 Open API 서비스는 아마존, 구글 등의 글로벌 회사들이 자사의 서비스를 일반 개발자 혹은 타사 등에 개방하여 다양한 서비스가 생겨나게 하며, 이것이 결국에 자사 비즈니스의 확대 및 수익 증대의 계기가 되었음이 입증 되었기에 Open API 를 이용하여 자사의 자원을 개방하는 서비스가 보편화 되어가고 있습니다.


Open API 의 데이터 표기형식

Open API 의 정보들은 표의 형태로 이루어져 있습니다. 많은 양의 정보가 적혀있는 데이터들을 사용하기 위해 스트림을 이용하여 데이터를 보내줘야 합니다. 그리고 스트림을 이용하게 되면 바이트 단위로 처리를 해주어야 하죠. 근데 바이트 단위로 보내면 데이터를 처리하기가 어려우니, 문자열 단위로 보내야겠다고 생각합니다.

근데 문자열 단위로 보내니, 정보의 구분이 안가기 시작합니다. 어떤게 이름이며, 어떤게 메시지인지 구분할수가 없는것이죠. 그래서 Open API 를 제공하는 기관에서는 데이터(자원) 을 공개할 때, 각 값들을 구분하기 위하여 3가지의 데이터 표기형식(Representation of Resource) 를 사용했습니다. 각 표기형식들에 대해 알아봅시다.

CSV(Comma Separate Value) 형식

콤마로 구분하여 데이터를 쓰고, 저장한 파일을 Open API 로 제공하는 형식입니다. 확장자는 .csv 입니다.

왕십리약국,서울도선동,021234,1025,1700
이수약국,서울사당동,024567
방배약국,ㅋㅋㅋㅋ,0123

위 데이터를 보면 데이터들이 콤마로 구분은 되지만 각 데이터들이 가지고 있는 값이 어떤 값인지 파악하기가 어렵습니다. 그래서 CSV 파일 대신에 다른 표기법을 사용할 필요가 생긴거죠. 그래서 채택된 방식이 xml 언어의 표기법 입니다.

xml (eXtensible markup language) 형식

<000>...</000> 라는 태그문으로 요소의 식별이 가능한 형식입니다.

<item>
        <title>왕십리약국</title>
        <addr>서울시 도선동</addr>
        <tel>02-214-2356</tel>
</item>
<item>
        <title>이수약국</title>
        <addr>서울시 사당동</addr>
        <tel>02-456-7892</tel>
</item>
<item>
        <title>방배약국</title>
        <addr>서울시 방배동</addr>
        <tel>02-447-5567</tel>
</item>

앞선 데이터를 xml 로 표기해보았습니다. csv 에 비해 각 데이터들이 어떠한 값인지 파악하기 용이한 모습입니다. 그래서 2010년 부터 지금까지도 xml 로 Open API 를 제공하는 기관들이 많습니다.

위 데이터를 사용자에게 텍스트 그대로 보여주면 알아볼 수 없으니, 이 xml 문서를 분석(Parse) 하여 화면에 보기 편한 형태로 만들어주어야 합니다. 이러한 과정을 'Open API 를 이용한 앱을 만든다' 라고 표현합니다.

다만, xml 의 태그문이 각 데이터를 식별하기 쉽게 만들어주지만 문자양이 너무 길어지기 때문에 현재는 json 으로 바꿔가는 추세 입니다.

json (JavaScript Object Notation) 형식

{"title":"왕십리약국","addr":"서울","tel":1234} , {"title":"이수약국","addr":"인천","tel":8887}

xml 단점을 보완하기 위해 json 이 사용되어가는 추세이며, 기관들도 xml 또는 json 으로 정보를 제공해줍니다.


XML Parsing

우리는 데이터가 필요합니다. 그리고 그러한 데이터는 기관으로부터 xml 파일의 형식으로 받아볼 수 있습니다. 다만, xml 정보는 사용자가 직접 이해하기 어렵기 때문에 우리는 xml 파일을 가져와 가공하여 사용자로 부터 이해하기 쉽게 만들어주어야 합니다. 그리고 그러기 위해서는 xml 코드를 분석해야 합니다. 원래라면 스트림과 if 문을 이용하여 xml 코드를 하나하나 분석해야하지만, 이러한 분석을 도와주는 클래스가 있습니다. 바로 XmlResourcePaser 와 XmlPullParcer 가 입니다.


res 폴더에 있는 xml 으로 파싱하기

일단 기관의 xml 파일을 바로 받아와 파싱하는 예제 이전에, 연습 삼아 프로젝트 안의 res 폴더에 xml 파일을 하나 만들고, 그 xml 파일부터 파싱해봅시다.

xml 파일 만들기

res 폴더안에 xml 폴더에 movies.xml 를 하나 만들고 다음과 같은 코드를 작성합시다.

<movies>
    <item>
        <no>1</no>
        <title>토토로</title>
        <genre>애니메이션</genre>
    </item>
    <item>
        <no>2</no>
        <title>포뇨</title>
        <genre>애니메이션</genre>
    </item>
    <item>
        <no>3</no>
        <title>동감</title>
        <genre>로맨스</genre>
    </item>
    <item>
        <no>4</no>
        <title>여고괴담</title>
        <genre>호러</genre>
    </item>
</movies>

이제 이 xml 파일을 파싱해보도록 하겠습니다. 간단하게 버튼하나와 텍스트뷰 하나를 만들어, 버튼을 누르면 movies.xml 을 파싱하여 텍스트뷰에 뿌려주는 예제입니다. 화면 구성은 간단하니 자바 코드만 살펴봅시다.

Parser 객체

public class MainActivity extends AppCompatActivity {

    TextView tv;

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

        tv = findViewById(R.id.tv);
        findViewById(R.id.btn).setOnClickListener(view -> clickBtn());
    }

    public void clickBtn(){
        Resources res = getResources();
        XmlResourceParser xml = res.getXml(R.xml.movies);

        try {
            xml.next();
            int eventType = xml.getEventType();

        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (XmlPullParserException e) {
            throw new RuntimeException(e);
        }

    }
}

우리는 Parser 객체를 이용하여 xml 파일을 파싱해주어야 합니다. 우선 Parser 객체를 이용하기 위해 Resource res = getResource(); 를 이용하여 Resource 객체를 먼저 얻어옵시다. 그리고 XmlResourceParser xml = res.getXml(R.xml.movies); 를 이용하면 XmlResourceParser 객체를 얻을 수 있습니다.

그리고 Parser 객체의 next() 메서드는 xml 파일의 태그를 읽어오는 메서드 입니다. 여기서 Xml 파일 분석의 이벤트 5가지를 보고 넘어갑시다.

XML 분석 이벤트 종류
1. START_DOCUMENT : XML 파일의 시작 태그를 의미합니다.
2. END_DOCUMENT : XML 파일의 종료 태그를 의미합니다.
3. START_TAG : 시작 태그를 의미합니다.
4. END_TAG : 종료 태그를 의미합니다.
5. TEXT : 시작태그와 종료태그 사이의 데이터를 의미합니다.

앞서 next() 메서드는 xml 파일의 태그를 읽어오는 메서드라고 하였습니다. 이 메서드는 위에서 본 분석 이벤트를 단위로 하여 xml 파일을 읽습니다. 즉, movies.xml 에서 next() 메서드로 읽히는 순서는 <movies> -> <item> -> <no> -> 1 -> </no> ... 순 입니다. 이 부분을 확실하게 파악하고 넘어갑시다.

그리고 next() 메서드의 경우 try-catch 문을 통해 예외처리를 해주어야 합니다.

while 문을 이용한 Parsing

Parser 객체도 만들었으므로 이제 Parsing 을 해봅시다. 일단 XmlResourceParser 객체의 경우 next() 메서드를 한번 호출 해줘야 시작 태그로 커서가 오기 때문에 앞선 코드에서 한번 호출해주었습니다.

try {
    xml.next();
    int eventType = xml.getEventType();
    StringBuffer buffer = new StringBuffer();

    while(eventType != XmlResourceParser.END_DOCUMENT){

        //7_ switch 문 활용
        switch (eventType){
            case XmlResourceParser.START_DOCUMENT:
                buffer.append("-- 파싱 작업을 시작합니다 --\n\n");
                break;

            case XmlResourceParser.END_DOCUMENT:
                break;
            case XmlResourceParser.START_TAG:
                String tagName = xml.getName();
                if(tagName.equals("item")){

                }else if(tagName.equals("no")){
                    buffer.append("순위 : ");
                }else if(tagName.equals("title")) {
                    buffer.append("제목 : ");
                }else if(tagName.equals("genre")){
                    buffer.append("장르 : ");
                }
                break;
            case XmlResourceParser.END_TAG:
                String tagName2 = xml.getName();
                if(tagName2.equals("item")){
                    buffer.append("\nㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ\n");
                }else {
                    buffer.append("\n");
                }
                break;
            case XmlResourceParser.TEXT:
                String text = xml.getText();
                buffer.append(text);
                break;
        }
        eventType = xml.next();
    } 
    buffer.append(" -- 파싱을 완료했습니다 --\n\n");
    tv.setText(buffer.toString());



} catch (IOException e) {
    throw new RuntimeException(e);
} catch (XmlPullParserException e) {
    throw new RuntimeException(e);
}

코드는 복잡해보이지만, 그리 어렵지 않습니다. 일단 우리가 하고자 하는 작업이 무엇인지 부터 파악합시다. 우리는 xml 에 저장되어 있는 데이터들을 우리가 읽기 쉬운 형태로 바꾸어 화면에 출력하고자 합니다. 그리고 우리는 태그문을 기준으로 데이터를 읽을 수 있는 Parser 객체를 이용할 수 있습니다. 그리고 읽은 태그문의 정보를 int eventType = xml.getEventType(); 을 이용하여 저장해주었습니다. 이제 이 eventType 변수와 switch 문을 이용하여 각각의 상황에 따라 제어를 해주겠습니다.

만약, Parser 가 읽어들인 태그가 START_DOCUMENT 라면 Parsing 작업이 시작된것입니다. 시작 태그를 읽은것일 테니 말이죠. 그래서 텍스트뷰에는 파싱 작업을 시작합니다 라는 문구를 띄우겠습니다. 자 그런데, 텍스트뷰에 바로 setText() 를 이용하여 문구를 띄우면 될까요? 되긴 됩니다. 예전에 했던 예제들에서도 이렇게 처리해주었던 예제도 있었습니다. 다만, 이런식의 코딩은 좋지 못한 코딩방식입니다.

앞서 String 객체는 immutable 한 성질을 가지고 있다고 하였습니다. 아주 자주 사용되는 객체이기 때문에 메모리의 효율성을 위해서 이러한 성질을 가진다고 하였죠. 그런데, 위처럼 코딩을 하게된다면 메모리적인 측면에서 아주 비효율적이 됩니다. 매번 데이터가 갱신될때마다 새로운 객체를 생성하는 코드가 될테니 말이죠. 그래서 이러한 경우라면, StringBuffer 클래스를 이용합니다. StringBuffer 클래스는 String 과 달리 바로 메모리에 올리지 않습니다. 일단 append 메소드를 이용하여 데이터를 추가시켜놓고, 추후에 한꺼번에 toString() 을 이용하여 데이터를 메모리에 올립니다. StringBuffer 는 따로 포스팅을 통해 좀 더 자세히 알아보겠습니다.

그리고 END_DOCUMENT 라면 어떨까요? xml 파일을 전부 읽은 상태 일테니 while 문을 종료되야 합니다. 그래서 위 코드에서도 while 문의 조건에 eventType != XmlResourceParser.END_DOCUMENT 을 이용하였습니다. 파서 객체가 읽어들인 태그가 END_DOCUMENT 일 때까지만 반복하겠다는 조건입니다.

이번에는 읽어들인 태그가 START_TAG 라면, 조금 복잡해집니다. START_TAG 에는 종류가 많기 때문이죠. <item>,<no> 등등이 있습니다. 그래서 각각의 상황을 if 문으로 나눠주고 버퍼에 append 해줍시다. 일단 TEXT 를 만난게 아니기 때문에 타이틀까지만 append 해주었습니다.

이번에는 TEXT 입니다. 파서를 이용해 읽어들인 데이터를 바로 append 해주면 됩니다.

마지막으로 END_TAG 입니다. END_TAG 를 만났다면, 줄바꿈을 해주어야 합니다. 그리고 영화 하나의 정보가 끝나고 다음 영화 정보로 넘어갈 때에는 줄을 하나 쳐주었습니다.

설명이 조금 길었지만 차근차근 읽어보면 어렵지 않은 구조입니다. 이렇게 해서 데이터를 파싱하는 방법을 알아보았습니다.


네트워크에서 xml 파일 파싱하기

Open API 사용하기

Open API 를 사용하기 위해서는 각 기관이 제공하는 Open API 의 사용법을 알아야 합니다. Open API 를 제공하는 기관에서는 Open API 의 사용법을 제시해주는데, 보통 REST API 를 활용한 방식을 많이 이용합니다. 이번 예제에서는 영화진흥위원회의 박스오피스 Open API 를 활용하여 Open API 의 사용법을 알아봅시다.

REST 방식을 이용하면 기본 요청 URL 의 주솟값을 받을 수 있습니다. 이 URL 이 박스오피스의 데이터를 담은 xml 파일입니다. 그리고 이 URL 에 추가적으로 요청할 수 있는 파라미터가 존재합니다. 요청 파라미터는 다음과 같습니다.

key 와 targetDt 요청 변수는 필수로 입력해주어야 하는 요청 변수 입니다. 각 설명에 맞게끔 값을 입력해주면 됩니다. 나머지 요청 인터페이스는 옵션입니다.

그리고 각 정보들을 응답필드로 불러올 수 있습니다. 응답 필드를 활용하는 방법은 밑의 XML Parsing 예제에서 자세히 알아봅시다.

리사이클러뷰 & 어댑터 만들기

우리는 버튼을 누르면 리사이클러뷰에 우리가 파싱한 정보를 띄우는 예제를 만들어볼겁니다. 그래서 메인 화면구성과 리사이클러뷰를 먼저 만들어봅시다. 이번 예제는 Xml 파일을 파싱하는것이 주 목적이기 때문에 코드만 작성하고 넘어갑시다.



------------ activity_main.xml
<LinearLayout ... 중략 >

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Load Data From Open API"
        android:textAllCaps="false"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        android:orientation="vertical"/>

</LinearLayout>



--------------- recyclerview_movieitem.xml
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    app:contentPadding="16dp"
    app:cardCornerRadius="8dp"
    android:layout_margin="4dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tv_rank"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:textColor="@color/purple_500"
            android:textSize="18sp"
            android:text="1"/>


        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:textColor="@color/purple_500"
            android:textSize="18sp"
            android:layout_toRightOf="@id/tv_rank"
            android:layout_marginLeft="20dp"
            android:text="movie_name"/>


        <TextView
            android:id="@+id/tv_open_dt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:textColor="@color/purple_500"
            android:textSize="18sp"
            android:text="2023-02-15"
            android:layout_marginTop="20dp"
            android:layout_below="@id/tv_title"/>


        <TextView
            android:id="@+id/tv_audi_acc"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:textColor="@color/purple_500"
            android:textSize="18sp"
            android:text="9010407"
            android:layout_marginTop="20dp"
            android:layout_alignParentRight="true"
            android:layout_alignBaseline="@id/tv_open_dt"/>

    </RelativeLayout>
</androidx.cardview.widget.CardView>



------------- MovieItem.java
public class MovieItem {
    String rank, movieNm, openDt, audiAcc;

    public MovieItem() {
    }

    public MovieItem(String rank, String movieNm, String openDt, String audiAcc) {
        this.rank = rank;
        this.movieNm = movieNm;
        this.openDt = openDt;
        this.audiAcc = audiAcc;
    }
}



------------- MovieAdapter.java
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.VH> {

    Context context;
    ArrayList<MovieItem> movieItems;

    public MovieAdapter(Context context, ArrayList<MovieItem> movieItems) {
        this.context = context;
        this.movieItems = movieItems;
    }

    @NonNull
    @Override
    public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new VH(LayoutInflater.from(context).inflate(R.layout.recyclerview_movieitem,parent,false));
    }

    @Override
    public void onBindViewHolder(@NonNull VH holder, int position) {
        MovieItem movieItem = movieItems.get(position);

        holder.tvRank.setText(movieItem.rank);
        holder.tvTitle.setText(movieItem.movieNm);
        holder.tvOpenDt.setText(movieItem.openDt);
        holder.tvAudiAcc.setText(movieItem.audiAcc);
    }

    @Override
    public int getItemCount() {
        return movieItems.size();
    }

    class VH extends RecyclerView.ViewHolder{

        TextView tvRank,tvTitle,tvOpenDt,tvAudiAcc;

        public VH(@NonNull View itemView) {
            super(itemView);

            tvRank = itemView.findViewById(R.id.tv_rank);
            tvTitle = itemView.findViewById(R.id.tv_title);
            tvOpenDt = itemView.findViewById(R.id.tv_open_dt);
            tvAudiAcc = itemView.findViewById(R.id.tv_audi_acc);
        }
    }
}

네트워크 작업 시작하기

리사이클러뷰도 만들어주었으니, 이제 리사이클러뷰에 담을 데이터를 XML Parsing 을 통해 가져와야 합니다. 그리고 우리가 가져올 xml 파일은 영화진흥위원회 서버에 있기 때문에 네트워크 작업이 필요하죠. 그래서 Xml Parsing 을 하기 이전에 네트워크 작업을 시작해봅시다.

public void clickBtn(){

        new Thread(){
            @Override
            public void run() {

                String address = "http://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.xml?key=f5eef3421c602c6cb7ea224104795888&targetDt=20120101";

                try {
                    URL url = new URL(address);
                    InputStream is = url.openStream();
                    InputStreamReader isr = new InputStreamReader(is); 
                    XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
                    XmlPullParser xpp = factory.newPullParser(); 
                    xpp.setInput(isr); 

                    int eventType = xpp.getEventType(); 
                    
                } catch (MalformedURLException e) {
                    throw new RuntimeException(e);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                } catch (XmlPullParserException e) {
                    throw new RuntimeException(e);
                }
            }
        }.start();
    }

네트워크 작업은 오래 걸리는 작업으로 인식하기 때문에 Main Thread 에서 작업할 수 없습니다. 그래서 별도의 Thread 를 만들어 네트워크 작업을 시작해주어야 합니다. 그리고 우리는 요청 url 에 있는 xml 을 사용해야 하므로 주소값을 일단 String 변수에 담아둡시다.

그리고 url 에 연결하기 위해서는 별도의 URL 객체가 필요합니다. 그리고 객체의 생성자로 아까 받아온 url 을 넣어주어야 합니다. 그리고 우리는 서버로 부터 데이터를 읽어와야 하므로, InputStream 을 이용하여 스트림을 생성해주어야 합니다. URL 객체에게 스트림을 열어달라 요청하고, 그 반환값을 InputStream 객체에 담아둡시다. 그리고 InputStream 으로는 바이트 데이터만 읽어올 수 있기 때문에 이를 문자열로 받아올 수 있게 도와주는 Reader 객체가 필요합니다. 그래서 InputStreamReader 객체를 만들고 생성자 파라미터로 아까 만든 InputStream 객체를 전달합시다.

이렇게 하면 서버로 부터 데이터를 읽을 1차적인 준비는 끝났습니다. 이제 Parser 를 준비할 차례입니다. 앞서 프로젝트 내부의 xml 파일에서 데이터를 읽어올 때 XmlResourceParser 를 사용했던것 처럼, 이번에는 XmlPullParser 를 이용해야 합니다. 그리고 이 XmlPullParser 객체를 만들기 위해서는 약간의 작업이 필요합니다. 먼저 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 을 이용하여 XmlPullParserFactory 객체를 하나 만들어 준 뒤, 이 객체를 이용해 XmlPullParser xpp = factory.newPullParser(); 와 같이 XmlPullParser 객체를 만들어 줄 수 있습니다. 그리고 xpp.setInput(isr); 를 이용해 파서에게 스트림을 통해 받아온 xml 리더를 전달합니다. 그러면 이제 xml 파일을 읽을 준비가 모두 끝납니다.

XML Parsing

public void clickBtn(){

    new Thread(){
        @Override
        public void run() {

            //String yesterday = new Date().toString(); 
            Date date = new Date();
            date.setTime(date.getTime() - (1000*60*60*24)); 
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            String yesterday = sdf.format(date);
            String address = "https://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.xml"
                    + "?key=" + key
                    + "&targetDt=" + yesterday
                    + "&itemPerPage=5";

            try {
                URL url = new URL(address);
                InputStream is = url.openStream();
                InputStreamReader isr = new InputStreamReader(is);
                XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
                XmlPullParser xpp = factory.newPullParser();
                xpp.setInput(isr); 

                int eventType = xpp.getEventType(); 

                MovieItem movieItem = null;

                while(eventType != XmlPullParser.END_DOCUMENT){



                    switch (eventType){
                        case XmlPullParser.START_DOCUMENT:
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(MainActivity.this, "파싱 작업이 시작되었습니다.", Toast.LENGTH_SHORT).show();
                                }
                            });
                            break;
                        case XmlPullParser.START_TAG:
                            String tagName = xpp.getName();

                            if(tagName.equals("dailyBoxOffice")){
                                movieItem = new MovieItem();
                            }
                            else if(tagName.equals("rank")){
                                xpp.next();
                                movieItem.rank = xpp.getText();
                            }
                            else if(tagName.equals("movieNm")){
                                xpp.next();
                                movieItem.movieNm = xpp.getText();
                            }
                            else if(tagName.equals("openDt")){
                                xpp.next();
                                movieItem.openDt = xpp.getText();
                            }
                            else if(tagName.equals("audiAcc")){
                                xpp.next();
                                movieItem.audiAcc = xpp.getText();
                            }
                            break;
                        case XmlPullParser.END_DOCUMENT:
                            break;
                        case XmlPullParser.END_TAG:
                            String tagName2 = xpp.getName();
                            if(tagName2.equals("dailyBoxOffice")){
                                movieItems.add(movieItem);
                            }
                            break;
                        case XmlPullParser.TEXT:
                            break;
                    }
                    eventType = xpp.next();
                }
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this, "파싱 작업이 끝났습니다.", Toast.LENGTH_SHORT).show();
                        adapter.notifyDataSetChanged();
                    }
                });


            }
            catch (MalformedURLException e) {
                throw new RuntimeException(e);
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
            catch (XmlPullParserException e) {
                throw new RuntimeException(e);
            }
        }
    }.start();
}

여기까지 했으면 나머지는 앞서 만들었던 예제와 크게 다르지 않습니다. while 문과 switch 문을 이용하여 각 태그를 기준으로 상황을 나누어 주면 됩니다. 다만 앞서 StringBuffer 에 데이터를 저장했던것과는 달리, 이번에는 리사이클러뷰를 이용하여 데이터를 화면에 띄워주어야 하므로, 리사이클러뷰에 데이터를 띄우기 위한 데이터 집합인 ArrayList 객체에 정보를 넣어주면 됩니다.

오늘 날짜를 기준으로 데이터 갱신하는 법이나 runOnUiThread 메서드 등은 어렵지 않거나 배운 내용들이므로 한번 읽어보고 넘어갑시다.

profile
Developer

0개의 댓글