我在运行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

如何解决此问题?


当前回答

Android不允许单独的进程进入主活动线程,HTTP连接在这里是一个独立的线程。这就是你得到“android.os.NetworkOnMainThreadException”的原因。

在向用户显示网页视图之前,您可能需要检查实际的Internet连接,因为如果没有Internet,网页视图将向用户显示页面未找到错误,通常您不知道要显示什么。

为了检查Internet可用性,可以使用ping命令,但在Wi-Fi情况下,可以在Wi-Fi服务器上禁用ping,因此在这种情况下,您使用HTTP连接来检查请求的状态。

如果在向用户显示Web视图之前检查自己的Web视图URL链接,这可能是正确的方法。在这种情况下,你可以使用Android的严格模式,但不要允许所有的策略,因为你不需要它。

您应该只为严格模式提供网络允许策略。只需将以下行添加到代码中,就不会出现此错误。

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitNetwork().build();
StrictMode.setThreadPolicy(policy);

其他回答

您也可以使用以下代码使用严格模式来解决此问题。这也是解决这个问题的一个替代方案。

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

但最好的做法是使用AsyncTask。

永远不要在UI线程上执行任何长时间运行的工作。长时间运行的工作可以是与服务器通信、读取/写入文件等。这些任务应该在后台线程上。这就是创建服务、异步任务和线程的原因。您可以禁用StrictMode,这将防止崩溃。但是,这是绝对不建议的。

我建议您至少在调试模式下利用StrictMode。使用下面的代码获取主线程上减慢应用程序速度的任何问题的日志。

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
            .detectAll()
            .penaltyLog()
            .build());

您可以设置不同的惩罚:

penaltyLog() // to print log
penaltyDeath() // This will crash you App(so costly penalty)
penaltyDialog() // Show alert when something went lazy on Main thread

这里有更多关于StrictMode的信息:StrictMode|Android开发者。

主线程是UI线程,您不能在主线程中执行可能会阻止用户交互的操作。您可以通过两种方式解决此问题:

强制在主线程中执行任务,如下所示

StrictMode.ThreadPolicy threadPolicy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(threadPolicy);

或者创建一个简单的处理程序并根据需要更新主线程。

Runnable runnable;
Handler newHandler;

newHandler = new Handler();
runnable = new Runnable() {
    @Override
    public void run() {
         try {
            //update UI
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }
};
newHandler.post(runnable);

要停止线程,请使用:

newHandler.removeCallbacks(runnable);

有关更多信息,请查看:无痛线程

不同的选项:

使用普通的Java可运行线程来处理网络任务,并且可以使用runOnUIThread()来更新UI如果您希望在获得网络响应后更新UI,可以使用intentservice/async任务

简单地说,

不在UI线程中执行网络工作

例如,如果您执行HTTP请求,则这是一个网络操作。

解决方案:

您必须创建一个新线程或使用AsyncTask类

Way:

把你所有的作品放进去

新线程的run()方法或AsyncTask类的doInBackground()方法。

But:

当您从网络响应中获得一些内容并希望在视图中显示它(如在TextView中显示响应消息)时,需要返回到UI线程。

如果不执行此操作,将获得ViewRootImpl$CalledFromWrongThreadException。

如何

使用AsyncTask时,从onPostExecute()方法更新视图或者调用runOnUiThread()方法并更新run()方法内的视图。