라바 세마리

20170103 기상청 날씨 정보 파싱(안드로이드) 2 본문

Android/날씨요정

20170103 기상청 날씨 정보 파싱(안드로이드) 2

3larvas 2017. 1. 4. 01:04

현재까지 완성된 부분

1. 기상청웹에서 날씨정보 파싱

2. 파싱한 정보 NodeList에 저장 및 화면출력

이다.


파싱은 금방했지만 화면출력하는 부분에서....해맸다.

작업스레드에서는 UI관련 작업을 할 수 없기때문에.... 

AsyncTask....Handler.....

덕분에 이것저것 몰랏던 것들을 많이알았다.


MainActivity.java


package com.example.weathertest; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.TextView; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button button; private TextView textView; private makeListThread thread; private Document document = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.textView); button = (Button) findViewById(R.id.button); button.setOnClickListener(this); thread = new makeListThread(); thread.start(); } public void makeList() { if (document != null) { NodeList nodeList = document.getElementsByTagName("data"); String s = ""; for (int i = 0; i < nodeList.getLength(); i++) { for (int k = 0; k < nodeList.item(i).getChildNodes().getLength(); k++) { if (nodeList.item(i).getChildNodes().item(k).getNodeType() == Node.ELEMENT_NODE) { System.out.print("nodeList"); s += k + ":" + nodeList.item(i).getChildNodes().item(k).getNodeName().toString() + "====>"; s += nodeList.item(i).getChildNodes().item(k).getTextContent().toString() + "\n"; } textView.setText(s); } } } } @Override public void onClick(View v) { switch(v.getId()) { case R.id.button : thread.stopThread(); document = thread.getDoc(); makeList(); break; } } }



makeListThread.java

package com.example.weathertest;

import android.util.Log;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;


public class makeListThread extends Thread {
    private boolean stopped = false;
    private Document doc = null;
    private static String urlStr = "http://www.kma.go.kr/wid/queryDFS.jsp?gridx=61&gridy=125";

    @Override
    public void run() {
        super.run();
        while(!stopped) {
            try {
                doc = getWeather();
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (SAXException e) {
                e.printStackTrace();
            }
        }
    }

    public void stopThread()
    {
        stopped = true;
    }

    public Document getDoc()
    {
        return doc;
    }


    public Document getWeather() throws ParserConfigurationException, IOException, SAXException {
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = builderFactory.newDocumentBuilder();
        URL urlForHttp = new URL(urlStr);

        InputStream instream = getInputStreamUsingHTTP(urlForHttp);
        Document document = builder.parse(instream);

        if (document != null) {
            NodeList list = document.getElementsByTagName("data");
            System.out.println("스레드실행");
            for (int i = 0; i < list.getLength(); i++) {
                System.out.println("=========================");
                for (int k = 0; k < list.item(i).getChildNodes().getLength(); k++) {
                    if (list.item(i).getChildNodes().item(k).getNodeType() == Node.ELEMENT_NODE) {
                        System.out.print(k + ":" + list.item(i).getChildNodes().item(k).getNodeName() + "====>");
                        System.out.println(list.item(i).getChildNodes().item(k).getTextContent());
                    }
                }
            }
            return document;
        }
        return null;
    }

    private InputStream getInputStreamUsingHTTP(URL urlForHttp) throws IOException {
        HttpURLConnection conn = (HttpURLConnection) urlForHttp.openConnection();
        conn.setRequestMethod("GET");
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setUseCaches(false);;
        conn.setAllowUserInteraction(false);
        int resCode = conn.getResponseCode();
        Log.d("TAG ::","Response code : " + resCode);
        InputStream instream = conn.getInputStream();
        return  instream;
    }
}





새로 알게된 것


1. 메인스레드와 작업스레드 정체 (Handler의 역할)

2. 간단하게 스레드를 구현하는 AsyncTask

3. XMLParsting(XML파싱)에서의 트리 구조

4. 스레드 죽이기


등을 새롭게 배웠다.


1. 메인스레드와 작업스레드의 정체


1-1. 도대체 왜 따로 있는건가?

안드로이드에서는 왠만한 작업이 메인스레드(UI스레드)에서 처리된다.

하지만 네트워크 관련 작업은 메인스레드에서 처리하지 못하게 한다.

이유는 시간이많이걸려서...?인 것으로 추정된다.

그래서 별도의 작업스레드를 만들어서 그 스레드안에서만 네트워크 작업을 처리하게한다.


1-2. 스레드에서의 작업시 주의사항은?

메인스레드가 UI스레드라고도 불리는 이유는 오직 메인스레드만이

UI관련 작업을 처리할 수 있기때문이다.( Ex. textView.setText("test"); )

그래서 결국 작업스레드에서 직접적으로 UI관련 작업은 할 수 없게된다.

하지만 Handler를 사용하면 UI를 간접적으로나마 작업스레드에서 건드릴수 있다.

UI관련 작업 명령을 Handler에 담아 UI스레드로 보내는 것이다.


2. 간단하게 스레드를 구현하는 AsyncTask

스레드를 선언해서 사용하다보면... handler...looper...message 이런저런 고려해야할 것들이 많다.

하지만 AsyncTask를 활용하면 스레드 직접 선언하는것 보다 간편하게 작업할수 있다.

각각의 함수(Ex. doInBackground)가 메인스레드에서 처리되는지 작업스레드에서 처리되는지를 잘 파악하고 있어야한다.


3. XMLParsting(XML파싱)에서의 트리 구조

웹에서 파싱해올때 XML문서내용을 트리 구조로 가져온다.

그래서 NodeList에 담을 수 있다.


4. 스레드 죽이기

문제해결에 아주 직접적으로 도움이된 부분이다.

작업스레드를 한번 생성하면 죽이지 않는이상 계속 작업스래드 작업만 반복된다.

메인스레드에 작성한 코드가 실행되지않는다.

그래서 플래그를 이용해 외부에서 작업스레드를 중지시켜야한다.


ㅁ느낀점

 하루 종일 붙잡고 있으니까 해결은 되는구나


ㅁ다음 포스팅에 게시될 내용

 지역설정, NodeList정보 관리,