Как я могу исправить 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 ]

43 голосов
/ 12 июня 2014

Использование Аннотации Android - опция.Это позволит вам просто запустить любой метод в фоновом потоке:

// normal method
private void normal() {
    doSomething(); // do something in background
}

@Background
protected void doSomething() 
    // run your networking code here
}

Обратите внимание, что, хотя он обеспечивает преимущества простоты и читаемости, он имеет свои недостатки.

42 голосов
/ 05 сентября 2013

Это происходит в Android 3.0 и выше. Начиная с Android 3.0 и выше, они ограничивали использование сетевых операций (функций, имеющих доступ к Интернету) в основном потоке / потоке пользовательского интерфейса (что порождается вашими методами создания и возобновления в действии).

Это поощряет использование отдельных потоков для сетевых операций. См. AsyncTask для более подробной информации о том, как правильно выполнять сетевые операции.

39 голосов
/ 16 июля 2014

Ошибка связана с выполнением длительных операций в основном потоке. Вы можете легко устранить проблему, используя AsynTask или Поток . Вы можете проверить эту библиотеку AsyncHTTPClient для лучшей обработки.

AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {

    @Override
    public void onStart() {
        // Called before a request is started
    }

    @Override
    public void onSuccess(int statusCode, Header[] headers, byte[] response) {
        // Called when response HTTP status is "200 OK"
    }

    @Override
    public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
        // Called when response HTTP status is "4XX" (for example, 401, 403, 404)
    }

    @Override
    public void onRetry(int retryNo) {
        // Called when request is retried
    }
});
38 голосов
/ 05 января 2014

Вы не должны выполнять никаких трудоемких задач в главном потоке (потоке пользовательского интерфейса), таких как любые сетевые операции, операции ввода-вывода файлов или операции с базами данных SQLite. Таким образом, для такого рода операций вы должны создать рабочий поток, но проблема в том, что вы не можете напрямую выполнять какие-либо операции, связанные с пользовательским интерфейсом, из вашего рабочего потока. Для этого вы должны использовать Handler и передать Message.

Чтобы упростить все эти вещи, Android предоставляет различные способы, такие как AsyncTask, AsyncTaskLoader, CursorLoader или IntentService. Таким образом, вы можете использовать любой из них в соответствии с вашими требованиями.

37 голосов
/ 18 июля 2013

Верх ответ от spektom отлично работает.

Если вы пишете AsyncTask inline, а не как класс, и поверх этого, если есть необходимостьчтобы получить ответ из AsyncTask, можно использовать метод get(), как показано ниже.

RSSFeed feed = new RetreiveFeedTask().execute(urlToRssFeed).get();

(из его примера.)

31 голосов
/ 25 февраля 2014

Используется только для приложений, ориентированных на Honeycomb SDK или выше. Приложениям, нацеленным на более ранние версии SDK, разрешено создавать сети в своих основных потоках цикла событий.

Ошибка предупреждения SDK!

26 голосов
/ 17 сентября 2013

Для меня это было так:

<uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="10" />

Устройство, на котором я тестировал мое приложение, было 4.1.2, которое является версией SDK 16!

Убедитесь, что целевой версией являетсятак же, как ваша целевая библиотека Android.Если вы не уверены, что является вашей целевой библиотекой, щелкните правой кнопкой мыши ваш Проект -> Путь сборки -> Android , и он должен быть отмечен.

Также, как уже упоминали другие, укажите правильные разрешения для доступа в Интернет:

<uses-permission android:name="android.permission.INTERNET"/>
23 голосов
/ 25 июня 2014

Просто, чтобы объяснить что-то явно:

Основной поток - это в основном поток пользовательского интерфейса.

То, что вы не можете выполнять сетевые операции в основном потоке, означает, что вы не можете выполнять сетевые операции впоток пользовательского интерфейса, что означает , что вы не можете выполнять сетевые операции в *runOnUiThread(new Runnable() { ... }* блоке внутри какого-либо другого потока, либо.

(у меня просто был долгий головокружительный момент, пытаясь выяснить,почему я получаю эту ошибку где-то, кроме моего основного потока. Именно поэтому этот поток помог, и, надеюсь, этот комментарий поможет кому-то еще.)

21 голосов
/ 21 июля 2014

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

Чтобы избежать этого, мы можем справиться с этим, используя потоков или исполнителей

Executors.newSingleThreadExecutor().submit(new Runnable() {
    @Override
    public void run() {
        // You can perform your task here.
    }
});
20 голосов
/ 01 марта 2014

Используйте это в своей деятельности

    btnsub.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub

                    //Initialize soap request + add parameters
                    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME1);

                    //Use this to add parameters
                    request.addProperty("pincode", txtpincode.getText().toString());
                    request.addProperty("bg", bloodgroup.getSelectedItem().toString());

                    //Declare the version of the SOAP request
                    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);

                    envelope.setOutputSoapObject(request);
                    envelope.dotNet = true;

                    try {
                        HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);

                        //this is the actual part that will call the webservice
                        androidHttpTransport.call(SOAP_ACTION1, envelope);

                        // Get the SoapResult from the envelope body.
                        SoapObject result = (SoapObject) envelope.getResponse();
                        Log.e("result data", "data" + result);
                        SoapObject root = (SoapObject) result.getProperty(0);
                        // SoapObject s_deals = (SoapObject) root.getProperty(0);
                        // SoapObject s_deals_1 = (SoapObject) s_deals.getProperty(0);
                        //

                        System.out.println("********Count : " + root.getPropertyCount());

                        value = new ArrayList<Detailinfo>();

                        for (int i = 0; i < root.getPropertyCount(); i++) {
                            SoapObject s_deals = (SoapObject) root.getProperty(i);
                            Detailinfo info = new Detailinfo();

                            info.setFirstName(s_deals.getProperty("Firstname").toString());
                            info.setLastName(s_deals.getProperty("Lastname").toString());
                            info.setDOB(s_deals.getProperty("DOB").toString());
                            info.setGender(s_deals.getProperty("Gender").toString());
                            info.setAddress(s_deals.getProperty("Address").toString());
                            info.setCity(s_deals.getProperty("City").toString());
                            info.setState(s_deals.getProperty("State").toString());
                            info.setPinecode(s_deals.getProperty("Pinecode").toString());
                            info.setMobile(s_deals.getProperty("Mobile").toString());
                            info.setEmail(s_deals.getProperty("Email").toString());
                            info.setBloodgroup(s_deals.getProperty("Bloodgroup").toString());
                            info.setAdddate(s_deals.getProperty("Adddate").toString());
                            info.setWaight(s_deals.getProperty("waight").toString());
                            value.add(info);
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    Intent intent = new Intent(getApplicationContext(), ComposeMail.class);
                    //intent.putParcelableArrayListExtra("valuesList", value);

                    startActivity(intent);
                }
            }).start();
        }
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...