我在运行RssReader的Android项目时出错。

代码:

URL url = new URL(urlToRssFeed);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xmlreader = parser.getXMLReader();
RssHandler theRSSHandler = new RssHandler();
xmlreader.setContentHandler(theRSSHandler);
InputSource is = new InputSource(url.openStream());
xmlreader.parse(is);
return theRSSHandler.getFeed();

它显示以下错误:

android.os.NetworkOnMainThreadException

如何解决此问题?


当前回答

您不应该在主线程(UI线程)上执行任何耗时的任务,如任何网络操作、文件I/O或SQLite数据库操作。因此,对于这种操作,您应该创建一个工作线程,但问题是您不能直接从工作线程执行任何与UI相关的操作。为此,您必须使用Handler并传递消息。

为了简化所有这些事情,Android提供了各种方式,如AsyncTask、AsyncTaskLoader、CursorLoader或IntentService。因此,您可以根据您的要求使用任何这些。

其他回答

不能在主线程或UI线程上调用网络。在Android上,如果你想呼叫网络,有两个选项-

调用asynctask,它将运行一个后台线程来处理网络操作。您可以创建自己的可运行线程来处理网络操作。

就我个人而言,我更喜欢异步任务。有关详细信息,请参阅此链接。

来自开发者android:

AsyncTask理想情况下应用于短操作(最多几秒钟)

使用newCachedThreadPool是一个好方法。还可以考虑其他选项,如newSingleThreadExecutor、newFixedThreadPool

    ExecutorService myExecutor = Executors.newCachedThreadPool();
    myExecutor.execute(new Runnable() {
        @Override
        public void run() {
            URL url = new URL(urls[0]);
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            XMLReader xmlreader = parser.getXMLReader();
            RssHandler theRSSHandler = new RssHandler();
            xmlreader.setContentHandler(theRSSHandler);
            InputSource is = new InputSource(url.openStream());
            xmlreader.parse(is);
        }
    });

ThreadPoolExecutor是一个帮助程序类,可使此过程更简单。这类管理一组线程的创建并管理如何在这些线程之间分配工作。随着工作量的增加或减少,该类会加速或破坏更多线程可根据工作负载进行调整。

有关Android线程的更多信息,请参阅本文。

您不能在蜂巢上的UI线程上执行网络I/O。从技术上讲,这在早期版本的Android上是可能的,但这是一个非常糟糕的想法,因为它会导致你的应用停止响应,并可能导致操作系统因你的应用行为不端而杀死你的应用。您需要运行后台进程或使用AsyncTask在后台线程上执行网络事务。

Android开发者网站上有一篇关于“无痛苦线程”的文章,这是一篇很好的介绍,它将为您提供比这里实际提供的答案更深入的答案。

不使用strictMode(仅在调试模式下)不更改SDK版本不要使用单独的线程

使用服务或异步任务

另请参阅堆栈溢出问题:

android.os.NetworkOnMainThreadException从android发送电子邮件

当应用程序尝试在其主线程上执行网络操作时,会引发此异常。如果您的任务耗时超过5秒,则需要强制关闭。

在AsyncTask中运行代码:

class RetrieveFeedTask extends AsyncTask<String, Void, Boolean> {

    protected RSSFeed doInBackground(String... urls) {
       // TODO: Connect
    }

    protected void onPostExecute(RSSFeed feed) {
        // TODO: Check this.exception
        // TODO: Do something with the feed
    }
}