我如何解决android.os.NetworkOnMainThreadException?

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

我该如何解决这个问题?

当应用程序尝试在其主线程上执行联网操作时,会引发此exception。 如果你的任务花费了五秒钟以上,那就需要一个关闭的力量。

AsyncTask运行你的代码:

 class RetrieveFeedTask extends AsyncTask { protected RSSFeed doInBackground(String... urls) { // TODO: Connect } protected void onPostExecute(RSSFeed feed) { // TODO: Check this.exception // TODO: Do something with the feed } } 

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

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

但最好的做法是使用AsyncTask。

我们也可以使用RxJava将网络操作移动到后台线程。 而且它也相当简单。

 webService.doSomething(someData) .subscribeOn(Schedulers.newThread())-- This for background thread .observeOn(AndroidSchedulers.mainThread()) -- for callback on UI .subscribe(result -> resultText.setText("It worked!"), e -> handleError(e)); 

你可以用RxJava做更多的事情。这里有一些RxJava的链接。 随意挖掘。

Android中的RxJava异步任务

http://blog.stablekernel.com/replace-asynctask-asynctaskloader-rx-observable-rxjava-android-patterns/

我用简单的方法解决了这个问题

我在oncreate StrictMode.enableDefaults();后添加了StrictMode.enableDefaults(); 解决了这个问题

要么

使用ServiceAsyncTask来解决这个问题

注意:

 Do not change SDK version Do not use a separate thread 

更多, 请检查这一点 。

如何解决android.os.NetworkOnMainThreadException

什么是NetworkOnMainThreadException:

在Android中,我们必须在UI线程(主线程)上执行所有的UI操作。 如果我们在主线程上执行后台操作或一些网络操作,那么我们有可能会发生这种exception,并且应用程序不会响应。

如何解决它:

为了避免这个问题,你必须使用另一个线程进行后台操作或者网络操作,比如使用asyncTask,并且使用一些库来进行像Volley,AsyncHttp等网络操作。

主线程是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); 

欲了解更多信息检查了这一点: 无痛穿线

在主线程上执行网络操作时,会引发android.os.NetworkOnMainThreadException。 你最好在AsyncTask中去除这个exception。 这样写:

  new AsyncTask(){ @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(); } 

你可以使用KOTLINANKO

KotlinAndroid的新官方语言更多关于它你可以在这里findhttps://kotlinlang.org/docs/tutorials/kotlin-android.html

Anko在Android中支持Kotlin库,在这里有一些文档https://github.com/Kotlin/anko

这个解决方案真的很有用,只有几行代码写在@AntonioLeiva https://antonioleiva.com/anko-background-kotlin-android/

 doAsync { var result = runLongTask() uiThread { toast(result) } } 

尽管简单,但在UI Thread上运行后台作业时会发生NetworkOnMainThread ,因此您必须做的一件事是在后台运行您的longTask job 。 您可以在Android应用程序中使用此方法和KotlinAnko进行操作。

你实际上可以开始一个新的线程,我有这个问题,并通过这种方式解决它。

发生NetworkOnMainThreadexception是因为您在默认线程(即UI线程)上调用了一些网络操作。 根据不允许的Android版本的Android 3 (Honeycomb),您应该在主线程之外调用网络操作。

您可以使用AsyncTask,IntentService或创建自己的线程并在run方法内调用。 有关更多信息,请访问连接到网络

由于Android正在使用单线程,因此您不应在主线程上执行任何网络操作。 有各种方法可以避免这种情况。

使用以下方法执行网络操作

  • Asysnctask :对于不需要太多时间的小型操作。
  • 意向服务 :对于需要大量时间的网络操作。
  • 使用像VolleyRetrofit这样的自定义库来处理复杂的网络操作

切勿使用StrictMode.setThreadPolicy(policy) ,因为它会冻结您的用户界面,并不是一个好主意。

您不能在主线程或UI线程上调用网络。 在Android上,如果你想调用网络有两个选项 –

  1. 调用asynctask,它将运行一个后台线程来处理网络操作。
  2. 您可以创建自己的可运行线程来处理网络操作。

我个人更喜欢asynctask。 有关更多信息,请参阅此链接 。

永远不要在UI线程上做长时间的工作,长时间运行的工作可以和服务器通信,读写文件等。这些任务应该在后台线程上,这就是ServiceAsyncTaskThreads创建的原因。 您可以禁用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 

有很多关于https://developer.android.com/reference/android/os/StrictMode.html

截至2018年,我会建议在Kotlin中使用RxJava进行网络抓取。 下面是一个简单的例子。

 Single.fromCallable { // Your Network Fetching Code Network.fetchHttp(url) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe { // What you need to do with your result on the view result -> view.updateScreen(result) } 

使用下面的代码来执行繁重的任务。

 // Your package here import java.util.List; import org.apache.http.NameValuePair; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.os.AsyncTask; import android.view.View.OnSystemUiVisibilityChangeListener; public class AsyncRequest extends AsyncTask { Context context; ProgressDialog pDialog; // Three Constructors public AsyncRequest(Activity a, String m, List p) { context = a; method = m; parameters = p; } public AsyncRequest(Activity a) { this.caller = (OnAsyncRequestComplete) a; context = a; } public String doInBackground(String... urls) { //Perform your task here return result; } public void onPreExecute() { pDialog = new ProgressDialog(context); pDialog.setMessage("Please wait.."); pDialog.setCancelable(false); pDialog.show(); } public void onProgressUpdate(Integer... progress) { // You can implement some progressBar and update it in this record. // setProgressPercent(progress[0]); } public void onPostExecute(String response) { if (pDialog != null && pDialog.isShowing()) { pDialog.dismiss(); } // Get the result here } protected void onCancelled(String response) { if (pDialog != null && pDialog.isShowing()) { pDialog.dismiss(); } } } 

在每个Activity的onCreate方法中写下以下代码

 if (android.os.Build.VERSION.SDK_INT > 8) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder() .permitAll().build(); StrictMode.setThreadPolicy(policy); } 

清单标签后,您必须简单地在manifest.xml中添加以下行

  

并在活动文件中绑定语句后添加以下代码

 if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); } 

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

在向用户显示webview之前,可能需要检查实际的Internet连接,因为如果没有Internet,Web视图将向用户显示页面未find错误,通常您不会显示哪些内容。

为了检查互联网的可用性,可以使用ping命令,但是如果在Wi-Fi服务器上可以禁用Wi-Fi ping,那么在这种情况下,您可以使用HTTP连接来检查请求的状态。

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

你只应该给严格模式的网络允许策略。 只需将下面的代码添加到代码中,就不会出现这个错误。

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