我在运行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
如何解决此问题?
这些答案需要更新,以使用更现代的方式连接到Internet上的服务器,并处理一般的异步任务。
例如,您可以在GoogleDriveAPI示例中找到使用Tasks的示例。在这种情况下也应使用相同的方法。我将使用OP的原始代码来演示这种方法。
首先,您需要定义一个非主线程执行器,并且只需要执行一次:
private val mExecutor: Executor = Executors.newSingleThreadExecutor()
然后在该执行器中处理逻辑,该执行器将在主线程之外运行
Tasks.call (mExecutor, Callable<String> {
val url = URL(urlToRssFeed)
val factory = SAXParserFactory.newInstance()
val parser = factory.newSAXParser()
val xmlreader = parser.getXMLReader()
val theRSSHandler = RssHandler()
xmlreader.setContentHandler(theRSSHandler)
val is = InputSource(url.openStream())
xmlreader.parse(is)
theRSSHandler.getFeed()
// Complete processing and return a String or other object.
// E.g., you could return Boolean indicating a success or failure.
return@Callable someResult
}).continueWith{
// it.result here is what your asynchronous task has returned
processResult(it.result)
}
continueWith子句将在异步任务完成后执行,您将有权访问任务通过其.result返回的值。
谷歌不推荐Android 11中的Android AsyncTask API。
即使在主活动之外创建线程类,只要在main中调用它,也会得到相同的错误。调用必须在一个可运行的线程内,但如果您需要一些异步代码在后台执行或稍后在这里执行,您可以查看Kotlin和Java的一些替代方案:
*https://stackoverflow.com/questions/58767733/android-asynctask-api-deprecating-in-android-11-what-are-the-alternatives*
特别适合我的是mayank1513对上面链接中可运行线程的Java8实现的回答。代码如下:
new Thread(() -> {
// do background stuff here
runOnUiThread(()->{
// OnPostExecute stuff here
});
}).start();
但是,您可以先在代码的某个部分定义线程,然后在其他地方启动它,如下所示:
线程定义
Thread thread = new Thread(() -> {
// do background stuff here
runOnUiThread(()->{
// OnPostExecute stuff here
});
});
线程调用
thread.start();
我希望这可以让人省去看到不推荐的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开发者。