●程式說明

=>把抓到的rss新聞標題用listview的方法呈現出來

=>點擊每一個listview就要抓到它的link連出去(丟到下一頁,載入webview)

=>再寫一個arraylist不是很好的做法,比較好的做法是寫一個類別來存rss的資料,或是用MAP/SimpleAdaper來做
 
(一)先自訂一個類別存放rss資料:RSSNewsItem=>這邊不用get和set,只放兩個field
public class RSSNewsItem {
    public String title;
    public String link;
}

 

(二)MyDataHandler

public class MyDataHandler extends DefaultHandler {
    boolean isTitle = false;
    boolean isItem =false;
    boolean isLink = false;
    public ArrayList<RSSNewsItem> data = new ArrayList<>();
    RSSNewsItem item;
 
 
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
        if (qName.equals("title"))
        {
            isTitle = true;
        }
        if (qName.equals("item"))
        {
            isItem = true;
            item = new RSSNewsItem();
        }
        if (qName.equals("link"))
        {
            isLink = true;
        }
 
 
    }
 
 
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
        if (qName.equals("title"))
        {
            isTitle = false;
        }
        if (qName.equals("item"))
        {
            isItem = false;
            data.add(item);
        }
        if (qName.equals("link"))
        {
            isLink = false;
        }
    }
 
 
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
        if (isItem && isTitle)
        {
            item.title = new String(ch, start, length);
            //Log.d("NET", new String(ch, start, length));
        }
        if (isItem && isLink)
        {
            item.link = new String(ch, start, length);
            // Log.d("NET", new String(ch, start, length));
        }
    }
}
 
**說明:
1.public ArrayList<RSSNewsItem> data new ArrayList<>();=>使用泛型來儲存 RSSNewsItem 物件
RSSNewsItem item;=>設定item為 RSSNewsItem物件
2.但抓回來資料會發現第一個頁面標題也被抓進來了,我們只需要在item tag中的標題,所以多一個判斷變數isItem=>當tag開始為item為true,並且最後判斷要isItem和isTitle都是true才抓標題資料,boolean isLink false; =>用來判斷link tag的開頭結尾
2.在判斷item開頭結尾的時候,如果是開頭,就立刻new一個 RSSNewsItem物件,如果是結尾,就把這個物件加到data這個arraylist中
3.增加isLink的判斷
4.最後判斷如果是在item中而且是title中的內容,就把資料存進item.title中; 如果是在item中而且是link中的內容,就把資料存進item.link中
 

(三)MainActivity.java

public class MainActivity extends AppCompatActivity {
    ListView lv;
    ArrayAdapter<String> adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lv=(ListView)findViewById(R.id.listview);
    }
 
 
    public void click(View view) {
        new Thread(){
            @Override
            public void run()
            {
                URL url = null;
                try {
                    url = new URL("https://udn.com/rssfeed/news/2/6638?ch=news");
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.connect();
                    InputStream inputStream;
                    inputStream = conn.getInputStream();
 
 
                    BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
                    final StringBuilder sb = new StringBuilder();
                    String str;
                    while ((str = br.readLine()) != null)
                    {
                        sb.append(str);
                    }
                    String result = sb.toString();
                    final MyDataHandler dataHandler = new MyDataHandler();
                    SAXParserFactory spf = SAXParserFactory.newInstance();
                    SAXParser sp = spf.newSAXParser();
                    XMLReader xr = sp.getXMLReader();
                    xr.setContentHandler(dataHandler);
                    xr.parse(new InputSource(new StringReader(result)));
 
 
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            ArrayList<String> forAdaper=new ArrayList<String>();
                            for (RSSNewsItem i:dataHandler.data){
                                forAdaper.add(i.title);
                            }
                            adapter=new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_list_item_1,forAdaper);
                            lv.setAdapter(adapter);
                            lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                                @Override
                                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                                    Intent in=new Intent(MainActivity.this,Detail.class);
                                    in.putExtra("link",dataHandler.data.get(i).link);
                                    startActivity(in);
                                }
                            });
                        }
                    });
 
 
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (ProtocolException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (ParserConfigurationException e) {
                    e.printStackTrace();
                } catch (SAXException e) {
                    e.printStackTrace();
                }
            }
 
 
        }.start();
    }
 
**說明:
1.前面都和抓rss作法一樣,但因為listview是在主執行緒,只有建立ui的執行緒才能使用它,要回ui thread,就要使用 runOnUiThread
2.透過arrayadapter把arraylist的資料丟給listview
3.因為listview只需要放title資料不需要放link資料,而且現在data這個arraylist中存放的是RSSNewsItem物件,所以這邊要再建一個 ArrayList<String> forAdapter,用來存放從data中抓出來的title資料
2.透過foreach迴圈,把data中的每一個title加到forAdapter中
3. new ArrayAdapter<String>時的資料來源就要改為forAdapter
4.設定OnItemClick監聽,並啟動intent
5.要丟過去的資料是 dataHandler.data.get(i).link=>data這個arraylist中的第i項物件,因為是 RSSNewsItem物件,所以可以用.link取得這個物件的link資料
 
 
(四)Detail.java
public class Detail extends AppCompatActivity {
WebView wv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
wv=(WebView)findViewById(R.id.wv);
wv.getSettings().setJavaScriptEnabled(true);
wv.setWebChromeClient(new WebChromeClient());
Intent in=getIntent();
String url=in.getStringExtra("link");
wv.loadUrl(url);
}
**說明:
1.設定webview=>javascript和 WebChromeClient
2.setWebChromeClient()void setWebChromeClient (WebChromeClient client)
=>Sets the chrome handler. This is an implementation of WebChromeClient for use in handling JavaScript dialogs, favicons, titles, and the progress. This will replace the current handler.
=>Parameters
client WebChromeClient: an implementation of WebChromeClient
3.用getIntet取得前面丟過來的intent,再用 getStringExtra取得前面丟過來的link資料,把link放到loadUrl中

 

●程式參考(GitHub):實作讀取新聞網站的RSS

arrow
arrow
    創作者介紹
    創作者 muchone 的頭像
    muchone

    簡單。生活。享受

    muchone 發表在 痞客邦 留言(0) 人氣()