●程式說明
=>把抓到的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
文章標籤
全站熱搜
留言列表