我如何解决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异步任务
我用简单的方法解决了这个问题
我在oncreate
StrictMode.enableDefaults();
后添加了StrictMode.enableDefaults();
解决了这个问题
要么
使用Service
或AsyncTask
来解决这个问题
注意:
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(); }
你可以使用KOTLIN
和ANKO
。
Kotlin是Android的新官方语言更多关于它你可以在这里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应用程序中使用此方法和Kotlin与Anko进行操作。
你实际上可以开始一个新的线程,我有这个问题,并通过这种方式解决它。
发生NetworkOnMainThreadexception是因为您在默认线程(即UI线程)上调用了一些网络操作。 根据不允许的Android版本的Android 3 (Honeycomb),您应该在主线程之外调用网络操作。
您可以使用AsyncTask,IntentService或创建自己的线程并在run方法内调用。 有关更多信息,请访问连接到网络 。
由于Android正在使用单线程,因此您不应在主线程上执行任何网络操作。 有各种方法可以避免这种情况。
使用以下方法执行网络操作
- Asysnctask :对于不需要太多时间的小型操作。
- 意向服务 :对于需要大量时间的网络操作。
- 使用像Volley和Retrofit这样的自定义库来处理复杂的网络操作
切勿使用StrictMode.setThreadPolicy(policy) ,因为它会冻结您的用户界面,并不是一个好主意。
您不能在主线程或UI线程上调用网络。 在Android上,如果你想调用网络有两个选项 –
- 调用asynctask,它将运行一个后台线程来处理网络操作。
- 您可以创建自己的可运行线程来处理网络操作。
我个人更喜欢asynctask。 有关更多信息,请参阅此链接 。
永远不要在UI线程上做长时间的工作,长时间运行的工作可以和服务器通信,读写文件等。这些任务应该在后台线程上,这就是Service
, AsyncTask
, Threads
创建的原因。 您可以禁用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);
- Android的东西UserSensor.Builder – 无法创建距离传感器驱动程序
- “使用Android aar库回答Native”ClassNotFoundException:kotlin.LazyKt
- 如何从java类中的kotlin类创建对象?
- Kotlin:null不能是非nulltypes的kotlin的值
- android java / kotlin recyclerview项目不可见
- 将传递lambda到Observable.subscribe in kotlin导致内存泄漏?
- 如何通过意图在kotlin传递自定义对象
- Proguard在Kotlin中剥离自定义注释
- 没有提供足够的数据给HAL,预期的位置