我在运行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
如何解决此问题?
29条答案
按热度按时间qrjkbowd1#
RxAndroid
是解决这个问题的另一个更好的替代方案,它使我们避免了创建线程,然后在Android UI线程上发布结果的麻烦。我们只需要指定需要执行任务的线程,并且所有任务都在内部处理。
1.通过指定
(Schedulers.io())
,RxAndroid将在不同的线程上运行getFavoriteMusicShows()
。1.通过使用
AndroidSchedulers.mainThread()
,我们希望在UI线程上观察到这个可观察的,即,我们希望我们的onNext()
回调在UI线程中被调用。zengzsys2#
这仅适用于针对HiveSDK或更高版本的应用程序。允许针对早期SDK版本的应用程序在其主事件循环线程上进行联网。
The error is the SDK warning!
8cdiaqws3#
我使用新的
Thread
解决了这个问题。4uqofj5v4#
公认的答案有一些明显的缺点。除非您“真正”知道自己在做什么,否则不建议使用AsyncTask进行联网。一些不利方面包括:
executeOnExecutor
方法并提供替代执行器)。在ICS上串行运行时工作良好的代码在Gingerbread上并发执行时可能会中断,比如说,如果您无意中有执行依赖项的顺序。如果您想避免短期内存泄漏,在所有平台上都有定义良好的执行特征,并且有构建真正健壮的网络处理的基础,那么您可能需要考虑:
1.使用一个为您做得很好的库-在this question中有一个很好的网络库比较,或者
1.使用e1d1e或
IntentService
代替,可能使用e1d 3d1e通过“活动”的onActivityResult
方法返回结果。意向服务方法
缺点:
AsyncTask
更多的代码和复杂性,尽管没有您想象的那么多IntentService
替换为等效的Service
实现来轻松控制这一点,比如this one。正面:
onActivityResult
方法接收下载结果Activity
中从AsyncTask
进行上传,但如果用户上下文切换出应用程序以进行电话呼叫,系统可能会在上传完成之前*终止应用程序。使用活动Service
终止应用程序的可能性更小。IntentService
(如我上面链接的版本),则可以通过Executor
控制并发级别。实施总结
您可以很容易地实现
IntentService
以在单个后台线程上执行下载。步骤1:创建
IntentService
以执行下载。您可以告诉它通过Intent
附加项下载什么,并将其传递给PendingIntent
以用于将结果返回到Activity
:步骤2:在清单中注册服务:
步骤3:从“活动”调用服务,传递服务将用于返回结果的PendingResult对象:
步骤4:在onActivityResult中处理结果:
可以使用包含完整工作的Android Studio/Gradle项目的GitHub项目here。
ibrsph3r5#
您不能在Hive上的UI线程上执行网络I/O。从技术上讲,这在早期版本的Android上是可能的,但这是一个非常糟糕的主意,因为它会导致你的应用停止响应,并可能导致操作系统因为你的应用表现不好而杀死你的应用。您需要运行后台进程或使用AsyncTask在后台线程上执行网络事务。
Android开发者网站上有一篇关于Painless Threading的文章,这是一篇很好的介绍,它将为您提供比这里实际提供的更深入的答案。
7fhtutme6#
这个问题有两种解决方案。
1.不要在主UI线程中使用网络调用。为此使用异步任务。
1.在*setContentView(R.layout.activity_main);*之后将以下代码写入MainActivity文件:
如果(android.os.Build.VERSION.SDK_INT>9){StrictMode.ThreadPolicy policy=new-StrictMode.ThreadPolicy.Builder().permitAll().Build();StrictModel.SetThreadPolicys(policy);}
并将下面的import语句导入到Java文件中。
mfpqipee7#
在另一个线程上执行网络操作。
例如:
并将其添加到文件AndroidManifest.xml:
fhg3lkii8#
1.不要使用strictMode(仅在调试模式下)
1.不要更改SDK版本
1.不要使用单独的螺纹
使用服务或异步任务
另请参阅堆栈溢出问题:
pepwfjgg9#
您可以使用以下代码禁用严格模式:
不建议这样做:使用
AsyncTask
接口。Full code for both the methods
bjp0bcyl10#
基于网络的操作无法在主线程上运行。您需要在子线程上运行所有基于网络的任务,或者实现AsyncTask。
这是如何在子线程中运行任务:
ktecyv1j11#
将代码放入:
或:
f0ofjuux12#
这在Android 3.0及以上版本中发生。从Android 3.0及以上版本开始,他们限制使用网络操作(访问互联网的功能)在主线程/UI线程中运行(从活动中的创建和恢复方法生成)。
这是为了鼓励使用单独的线程进行网络操作。有关如何正确执行网络活动的更多详细信息,请参阅AsyncTask。
f45qwnt813#
可以选择使用Android Annotations。它将允许您在后台线程中简单地运行任何方法:
注意,尽管它提供了简单易读的优点,但也有其缺点。
isr3a4wc14#
该错误是由于在主线程中执行长时间运行的操作导致的,您可以使用AsynTask或Thread轻松纠正该问题。您可以 checkout 此库AsyncHTTPClient以获得更好的处理。
up9lanfz15#
您不应该在主线程(UI线程)上执行任何耗时的任务,如任何网络操作、文件I/O或SQLite数据库操作。因此,对于这种操作,您应该创建一个工作线程,但问题是您不能从工作线程直接执行任何与UI相关的操作。为此,您必须使用
Handler
并通过Message
。为了简化所有这些,Android提供了多种方式,如
AsyncTask
、AsyncTaskLoader
、CursorLoader
或IntentService
。因此,您可以根据您的需求使用这些。