我在运行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返回的值。
您可以将代码的一部分移动到另一个线程中以卸载主线程,并避免获得ANR、NetworkOnMainThreadException、IllegalStateException(例如,无法访问主线程上的数据库,因为它可能会长时间锁定UI)。
你应该根据情况选择一些方法
Java线程或Android HandlerThread:
Java线程只能一次性使用,并在执行其运行方法后死亡。HandlerThread是一个方便的类,用于启动具有looper的新线程。
AsyncTask(API级别30中已弃用)
AsyncTask被设计为围绕线程和处理程序的帮助类,不构成通用线程框架。AsyncTasks最好用于短操作(最多几秒钟)。如果需要让线程长时间运行,强烈建议您使用java.util.concurrent包提供的各种API,如Executor、ThreadPoolExecutor和FutureTask。
由于主线程独占UI组件,因此不可能访问某些视图,这就是为什么Handler会出手相助的原因
[执行器框架]
实现ExecutorService的ThreadPoolExecutor类,该类可以对线程池进行精细控制(例如,核心池大小、最大池大小、保活时间等)ScheduledThreadPoolExecutor-一个扩展ThreadPoolExecuto的类。它可以在给定延迟后或周期性地安排任务。
未来任务
FutureTask执行异步处理,但是,如果结果尚未就绪或处理尚未完成,则调用get()将阻塞线程
异步任务加载器
AsyncTaskLoader,因为它们解决了AsyncTask固有的许多问题
Intent服务
这是Android上长期运行处理的事实选择,一个很好的例子就是上传或下载大型文件。即使用户退出应用程序,上传和下载也可能会继续,并且您当然不想阻止用户在执行这些任务时使用应用程序。
作业调度程序
实际上,您必须使用JobInfo.Builder创建一个服务并创建一个作业,该作业指定了何时运行服务的条件。
RxJava语言
通过使用可观察序列来组合异步和基于事件的程序的库。
花冠(Kotlin)
它的主要要点是,它使异步代码看起来非常像同步代码
在这里、这里、这里和这里阅读更多信息。