You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RSS Feed无法填充TextView问题排查求助

BBC RSS Feed 无法填充TextView的问题排查

问题描述

我正在开发一个新闻阅读器项目,需将BBC的RSS Feed加载到TextView中。代码逻辑看似无误,但TextView始终无法填充内容,调试后怀疑是未正确实现open stream导致的。相关代码如下:

package com.example.finalproject_newsapp;

import androidx.appcompat.app.AppCompatActivity;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import android.os.Bundle;
import android.widget.ListView;
import android.widget.TextView;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

public class MainActivity extends AppCompatActivity {

    String rss = "";
    boolean item = false;

    private class RSSHandler extends DefaultHandler {

        public void startElement(String uri, String localName, String qName,
                                 Attributes attrs) throws SAXException {
            if (localName.equals("item"))
                item = true;

            if (!localName.equals("item") && item == true)
                rss = rss + localName + ": ";

        }

        public void endElement(String namespaceURI, String localName,
                               String qName) throws SAXException {

        }

        public void characters(char[] ch, int start, int length)
                throws SAXException {
            String cdata = new String(ch, start, length);
            if (item == true)
                rss = rss + (cdata.trim()).replaceAll("\\s+", " ") + "	";

        }
    }

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

        TextView feed = findViewById(R.id.BBC_feed);

        try {
            URL rssUrl = new URL("http://feeds.bbci.co.uk/news/world/us_and_canada/rss.xml");
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser saxParser = factory.newSAXParser();
            XMLReader xmlReader = saxParser.getXMLReader();
            RSSHandler rssHandler = new RSSHandler();
            xmlReader.setContentHandler(rssHandler);
            InputSource inputSource = new InputSource(rssUrl.openStream());
            xmlReader.parse(inputSource);
        } catch (MalformedURLException | ParserConfigurationException | SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        feed.setText(rss);
    }
}

问题原因排查

  • 主线程网络操作被拦截:Android从API 9开始禁止在主线程(如onCreate方法)执行网络请求,代码里的rssUrl.openStream()会触发NetworkOnMainThreadException,但当前异常捕获未覆盖该异常(或堆栈打印被忽略),导致RSS解析完全没执行,rss字符串始终为空。
  • SAX解析未处理命名空间:BBC的RSS Feed带有命名空间,默认SAX配置未开启命名空间支持,导致localName无法获取正确标签名(实际标签带命名空间前缀),localName.equals("item")判断永远不成立,item变量一直为false,不会往rss里拼接内容。
  • 缺少item结束标签处理:endElement方法无逻辑,解析完item标签后item变量不会重置为false,后续非item标签可能被错误拼接,但这不是空内容的主要原因。
  • 无网络权限:如果AndroidManifest.xml未添加<uses-permission android:name="android.permission.INTERNET"/>,网络请求直接失败,rss自然为空。

修复建议

  • 将网络操作移到子线程:把RSS解析逻辑放到子线程执行,完成后回到主线程更新TextView,示例代码:
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                URL rssUrl = new URL("http://feeds.bbci.co.uk/news/world/us_and_canada/rss.xml");
                SAXParserFactory factory = SAXParserFactory.newInstance();
                factory.setNamespaceAware(true); // 开启命名空间支持
                SAXParser saxParser = factory.newSAXParser();
                XMLReader xmlReader = saxParser.getXMLReader();
                RSSHandler rssHandler = new RSSHandler();
                xmlReader.setContentHandler(rssHandler);
                InputSource inputSource = new InputSource(rssUrl.openStream());
                xmlReader.parse(inputSource);
                // 回到主线程更新UI
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        feed.setText(rss);
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
                runOnUiThread(() -> feed.setText("加载失败:" + e.getMessage()));
            }
        }
    }).start();
    
  • 开启SAX命名空间支持:创建SAXParserFactory后调用factory.setNamespaceAware(true);,确保localName能正确获取不带命名空间的标签名。
  • 完善endElement逻辑:在endElement方法中添加代码,遇到item结束标签时重置item为false,并给每个item添加换行分隔:
    @Override
    public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
        if (localName.equals("item")) {
            item = false;
            rss += "\n\n";
        }
    }
    
  • 添加网络权限:在AndroidManifest.xml中添加网络权限声明:
    <uses-permission android:name="android.permission.INTERNET"/>
    

内容的提问来源于stack exchange,提问作者ReginaldRey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:57:24