我在运行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 3.0及更高版本中发生。从Android 3.0及更高版本开始,他们限制在主线程/UI线程中运行网络操作(访问Internet的功能)(活动中创建和恢复方法产生的内容)。

这是为了鼓励在网络操作中使用单独的线程。有关如何正确执行网络活动的详细信息,请参阅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线程的更多信息,请参阅本文。

我解决了在Kotlin使用线程的问题。有很多使用Java的例子,所以我想在Kotlin中添加一个适合我的解决方案。

 Thread {
     println("NEW THREAD")
     callAPI() // add your own task
 }.start()

因此,正如许多其他人所解释的那样,您不能在调用时阻塞主线程,因此有必要创建一个新线程。

这里有一个使用OkHttp、Future、ExecutorService和Callable的简单解决方案:

final OkHttpClient httpClient = new OkHttpClient();
final ExecutorService executor = newFixedThreadPool(3);

final Request request = new Request.Builder().url("http://example.com").build();

Response response = executor.submit(new Callable<Response>() {
   public Response call() throws IOException {
      return httpClient.newCall(request).execute();
   }
}).get();

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

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

但最好的做法是使用AsyncTask。

在主线程上执行网络操作时,将引发android.os.NetworkOnMainThreadException。您最好在AsyncTask中执行此操作以删除此异常。这样写:

    new AsyncTask<Void,String,String>(){

        @Override
        protected Void doInBackground(Void... params) {
            // Perform your network operation.
            // Get JSON or XML string from the server.
            // Store in a local variable (say response) and return.
            return response;
        }

        protected void onPostExecute(String results){
            // Response returned by doInBackGround() will be received
            // by onPostExecute(String results).
            // Now manipulate your jason/xml String(results).
        }

    }.execute();
}