Как я могу исправить android.os.NetworkOnMainThreadException? - PullRequest
2239 голосов
/ 14 июня 2011

Я получил ошибку при запуске моего проекта Android для RssReader.

Код:

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

Как я могу исправить эту проблему?

Ответы [ 53 ]

2 голосов
/ 02 марта 2017

Поскольку Android работает в одном потоке, вы не должны выполнять никаких сетевых операций в основном потоке. Есть разные способы избежать этого.

Используйте следующий способ для выполнения сетевых операций

  • Asysnctask : Для небольших операций, которые не занимают много времени.
  • Intent Service : для работы в сети, которая занимает много времени.
  • Используйте пользовательскую библиотеку, такую ​​как Volley и Retrofit для обработки сложные сетевые операции

Никогда не используйте StrictMode.setThreadPolicy (policy) , так как это замораживает ваш пользовательский интерфейс и не является хорошей идеей.

2 голосов
/ 10 июня 2019

Сделайте это в фоновом потоке, используя AsycTask

Java

class NetworkThread extends AsyncTask<String, Void, String> {

    protected Void doInBackground(String... arg0) {
        //Your implementation
    }

    protected void onPostExecute(String result) {
        // TODO: do something with the feed
    }
}

Звоните куда вам нужно

new NetworkThread().execute("Your URL here");

Kotlin

internal class MyNetworkTask : AsyncTask<String, Void, RSSFeed>() {

    override fun doInBackground(vararg urls: String): RSSFeed? {
        try {
             // download
             // prepare RSSFeeds
             return RSSFeeds
         } catch (e: Exception) {
            //handle exception
            return null
        }
    }

    override fun onPostExecute(feed: RSSFeed) {
        // TODO: check this.exception
        // TODO: do something with the feed
    }
}

Позвоните в kotlin

MyNetworkTask().execute(url)
1 голос
/ 19 января 2016

Исключение NetworkOnMainThread возникает из-за того, что вы вызвали сетевую операцию в потоке по умолчанию, то есть в потоке пользовательского интерфейса. Согласно версии Android Android 3 (Honeycomb), которая запрещена, вы должны вызывать сетевую операцию вне основного потока.

Вы можете использовать AsyncTask, IntentService или создать свой собственный поток и вызвать метод run. Для получения дополнительной информации посетите Подключение к сети .

1 голос
/ 17 августа 2015

Вы действительно можете начать новую тему, у меня была эта проблема раньше, и я решил ее таким образом.

1 голос
/ 11 декабря 2018

Если вы работаете в kotlin и anko, вы можете добавить

 doAsync {
   method()
}
0 голосов
/ 27 января 2015

Используйте приведенный ниже код для выполнения тяжелых задач.

// 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<String, Integer, String> {

    Context context;
    ProgressDialog pDialog;

    // Three Constructors
    public AsyncRequest(Activity a, String m, List<NameValuePair> 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();
        }
    }
}
0 голосов
/ 01 июня 2019

версия Kotlin

internal class RetrieveFeedTask : AsyncTask<String, Void, RSSFeed>() {

    override fun doInBackground(vararg urls: String): RSSFeed? {

        try {
             // download
             // prepare RSSFeeds
             return RSSFeeds

         } catch (e: Exception) {

            //handle exception
            return null
        }
    }

    override fun onPostExecute(feed: RSSFeed) {
        // TODO: check this.exception
        // TODO: do something with the feed
    }
}

Пример вызова,

RetrieveFeedTask().execute(url)
0 голосов
/ 01 марта 2019

Вы можете использовать Kotlin-coroutines

 class YoutActivity : AppCompatActivity, CoroutineScope {

      override fun onCreate(...) {
         launch {  yourHeavyMethod() }
      }

      suspend fun yourHeavyMethod() {
         async{ yourNetworkCall() }.await()
         ...
         ...
      }

 } 

Вы можете следовать этому руководству.

0 голосов
/ 10 мая 2018

Различные параметры:

  1. использовать обычный поток Java для выполнения сетевой задачи и использовать runOnUIThread () для обновления пользовательского интерфейса

  2. intentserviceЗадача / async может использоваться, если вы хотите обновить пользовательский интерфейс после получения сетевого ответа

0 голосов
/ 12 декабря 2014

Android не разрешает отдельный процесс в основной поток активности, и HTTP-соединение здесь является независимым потоком. По этой причине вы получаете " android.os.NetworkOnMainThreadException ".

Может возникнуть необходимость проверить фактическое подключение к Интернету перед отображением веб-просмотра для пользователя, потому что при отсутствии Интернета в веб-представлении отобразится ошибка Страница не найдена , чего обычно не показываешь.

Для проверки доступности Интернета можно использовать команду ping, но в случае Wi-Fi на сервере Wi-Fi можно отключить пинг, поэтому в этом случае вы используете HTTP-соединение для проверки состояния запроса.

Это может быть правильным подходом, если вы проверяете собственную URL-ссылку веб-просмотра, прежде чем показывать веб-просмотр пользователю. В этом случае вы можете использовать строгий режим Android, но не разрешать всю политику, потому что она вам не нужна.

Вы должны указывать политику сетевого доступа только для строгого режима. Просто добавьте следующую строку в ваш код, и вы не получите эту ошибку.

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitNetwork().build();
StrictMode.setThreadPolicy(policy);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...