Jak naprawić Androida.os.NetworkOnMainThreadException?

Dostałem błąd podczas uruchamiania mojego projektu Android dla RssReader.

Kod:

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();

I pokazuje poniższy błąd:

android.os.NetworkOnMainThreadException

Jak mogę rozwiązać ten problem?

Author: Ali Esa Assadi, 2011-06-14

30 answers

Ten wyjątek jest wyrzucany, gdy aplikacja próbuje wykonać operację sieciową w swoim głównym wątku. Uruchom swój kod w AsyncTask:

class RetrieveFeedTask extends AsyncTask<String, Void, RSSFeed> {

    private Exception exception;

    protected RSSFeed doInBackground(String... urls) {
        try {
            URL url = new URL(urls[0]);
            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();
        } catch (Exception e) {
            this.exception = e;

            return null;
        } finally {
            is.close();
        }
    }

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

Jak wykonać zadanie:

W pliku MainActivity.java możesz dodać tę linię w swojej metodzie oncreate()

new RetrieveFeedTask().execute(urlToRssFeed);

Nie zapomnij dodać tego do AndroidManifest.xml pliku:

<uses-permission android:name="android.permission.INTERNET"/>
 2281
Author: spektom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-28 11:57:55

Prawie zawsze należy uruchamiać operacje sieciowe w wątku lub jako zadanie asynchroniczne.

Ale jest możliwe usunięcie tego ograniczenia i nadpisanie domyślnego zachowania, jeśli chcesz zaakceptować konsekwencje.

Dodaj:

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

StrictMode.setThreadPolicy(policy); 

W twojej klasie,

I

Dodaj to uprawnienie w manifeście Androida.plik xml:

<uses-permission android:name="android.permission.INTERNET"/>

Konsekwencje:

Twoja aplikacja (w obszarach spotty połączenia z Internetem) stanie się użytkownik odczuwa powolność i musi zabić siłą, a ty ryzykujesz, że menedżer aktywności zabije Twoją aplikację i poinformuje użytkownika, że aplikacja została zatrzymana.

Android ma kilka dobrych wskazówek na temat dobrych praktyk programistycznych, aby zaprojektować responsywność: http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html

 580
Author: user1169115,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-11 14:18:49

Rozwiązałem ten problem używając nowego Thread.

Thread thread = new Thread(new Runnable() {

    @Override
    public void run() {
        try  {
            //Your code goes here
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});

thread.start(); 
 364
Author: Dr.Luiji,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-05 09:42:24

Nie można wykonać sieci I/Ow wątku UI na Honeycomb. Technicznie rzecz biorąc, to jest możliwe we wcześniejszych wersjach Androida, ale jest to naprawdę zły pomysł, ponieważ spowoduje to, że aplikacja przestanie odpowiadać i może spowodować, że system operacyjny zabije Twoją aplikację za złe zachowanie. Musisz uruchomić proces w tle lub użyć funkcji AsyncTask, aby wykonać transakcję sieciową w wątku w tle.

Jest artykuł o bezbolesne Gwintowanie na Androida strona dewelopera, która jest dobrym wstępem do tego, i zapewni Ci znacznie lepszą głębię odpowiedzi, niż można realistycznie podać tutaj.

 129
Author: Mark Allison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-09 16:25:22

Przyjęta odpowiedź ma kilka znaczących stron w dół. Nie jest wskazane, aby używać AsyncTask do sieci, chyba że naprawdę wiesz, co robisz. Niektóre z down-boków to:

  • AsyncTask utworzone jako niestatyczne klasy wewnętrzne mają ukryte odniesienie do otaczającego obiektu Activity, jego kontekstu i całej hierarchii widoków utworzonej przez tę aktywność. To odniesienie zapobiega zbieraniu śmieci do momentu, w którym AsyncTask będzie w tle praca zakończona. Jeśli połączenie użytkownika jest wolne i / lub pobieranie jest Duże, te krótkotrwałe wycieki pamięci mogą stanowić problem - na przykład jeśli orientacja zmienia się kilka razy (i nie anulujesz wykonywanych zadań) lub użytkownik odchodzi od aktywności.
  • AsyncTask ma różne właściwości wykonawcze w zależności od platformy, na której jest wykonywany: przed poziomem API 4 AsyncTask wykonuje się seryjnie na jednym wątku tła; od poziomu API 4 do poziomu API 10, AsyncTasks wykonuje na puli do 128 wątków; począwszy od poziomu API 11 AsyncTask wykonuje seryjnie na jednym wątku tła (chyba że użyjesz przeciążonej metody executeOnExecutor i dostarczysz alternatywnego executora). Kod, który działa dobrze, gdy jest uruchamiany seryjnie na ICS, może się zepsuć, gdy jest wykonywany jednocześnie na Gingerbread, powiedzmy, jeśli masz nieumyślne zależności od kolejności wykonania.

Jeśli chcesz uniknąć wycieków pamięci krótkotrwałej, miej dobrze zdefiniowaną charakterystykę wykonania we wszystkich platformy i mają podstawę do zbudowania naprawdę solidnej obsługi sieci, warto rozważyć: {]}

    W tym kontekście warto zwrócić uwagę na to, że biblioteki sieciowe są w pełni kompatybilne z bibliotekami sieciowymi, które są w pełni kompatybilne z bibliotekami sieciowymi.]}
  1. używając zamiast tego Service lub IntentService, być może za pomocą PendingIntent, aby zwrócić wynik za pomocą metody onActivityResult działania.

IntentService approach

Dół-boki:

  • więcej kodu i złożoności niż AsyncTask, choć nie tak bardzo, jak myślisz
  • ustawia żądania w kolejce i uruchamia je na pojedynczym wątku w tle. Można to łatwo kontrolować, zastępując IntentService równoważną implementacją Service, Być może jak ta .
  • Um, I can ' t think of any other right actually

Up-sides:

  • unika problemu wycieku pamięci krótkotrwałej
  • jeśli Twoja aktywność zostanie uruchomiona ponownie, gdy operacje sieciowe są w locie, nadal może otrzymać wynik pobierania za pomocą metody onActivityResult
  • lepsza Platforma niż AsyncTask do budowania i ponownego wykorzystania solidnego kodu sieciowego. Przykład: jeśli musisz wykonać ważne przesłanie, możesz to zrobić z AsyncTask W Activity, ale jeśli kontekst użytkownika wyłącza się z aplikacji, aby wykonać połączenie telefoniczne, system Może zabić aplikację przed zakończeniem przesyłania. Jest mniej prawdopodobne, aby zabić aplikację z aktywnym Service.
  • jeśli używasz własnej współbieżnej wersji IntentService (jak ten, który podlinkowałem powyżej) możesz kontrolować poziom współbieżności za pomocą Executor.

Podsumowanie realizacji

Możesz zaimplementować IntentService, aby dość łatwo pobierać pliki w jednym wątku tła.

Krok 1: Utwórz IntentService, aby wykonać pobieranie. Możesz powiedzieć, co pobrać za pomocą Intent extra ' s, i przekazać go PendingIntent, aby użyć do powrotu wyniku do Activity:

import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Intent;
import android.util.Log;

import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

public class DownloadIntentService extends IntentService {

    private static final String TAG = DownloadIntentService.class.getSimpleName();

    public static final String PENDING_RESULT_EXTRA = "pending_result";
    public static final String URL_EXTRA = "url";
    public static final String RSS_RESULT_EXTRA = "url";

    public static final int RESULT_CODE = 0;
    public static final int INVALID_URL_CODE = 1;
    public static final int ERROR_CODE = 2;

    private IllustrativeRSSParser parser;

    public DownloadIntentService() {
        super(TAG);

        // make one and re-use, in the case where more than one intent is queued
        parser = new IllustrativeRSSParser();
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        PendingIntent reply = intent.getParcelableExtra(PENDING_RESULT_EXTRA);
        InputStream in = null;
        try {
            try {
                URL url = new URL(intent.getStringExtra(URL_EXTRA));
                IllustrativeRSS rss = parser.parse(in = url.openStream());

                Intent result = new Intent();
                result.putExtra(RSS_RESULT_EXTRA, rss);

                reply.send(this, RESULT_CODE, result);
            } catch (MalformedURLException exc) {
                reply.send(INVALID_URL_CODE);
            } catch (Exception exc) {
                // could do better by treating the different sax/xml exceptions individually
                reply.send(ERROR_CODE);
            }
        } catch (PendingIntent.CanceledException exc) {
            Log.i(TAG, "reply cancelled", exc);
        }
    }
}

Krok 2: Zarejestruj usługę w "manifest": {]}

<service
        android:name=".DownloadIntentService"
        android:exported="false"/>

Krok 3: wywołaj usługę z aktywności, przekazując obiekt PendingResult, którego usługa użyje do zwrócenia wyniku:

PendingIntent pendingResult = createPendingResult(
    RSS_DOWNLOAD_REQUEST_CODE, new Intent(), 0);
Intent intent = new Intent(getApplicationContext(), DownloadIntentService.class);
intent.putExtra(DownloadIntentService.URL_EXTRA, URL);
intent.putExtra(DownloadIntentService.PENDING_RESULT_EXTRA, pendingResult);
startService(intent);

Krok 4: obsłuż wynik w onActivityResult:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == RSS_DOWNLOAD_REQUEST_CODE) {
        switch (resultCode) {
            case DownloadIntentService.INVALID_URL_CODE:
                handleInvalidURL();
                break;
            case DownloadIntentService.ERROR_CODE:
                handleError(data);
                break;
            case DownloadIntentService.RESULT_CODE:
                handleRSS(data);
                break;
        }
        handleRSS(data);
    }
    super.onActivityResult(requestCode, resultCode, data);
}

Projekt github zawierający kompletny działający projekt Android-Studio/gradle jest dostępny tutaj .

 125
Author: Stevie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:44
  1. nie używaj strictMode (tylko w trybie debugowania)
  2. nie zmieniaj wersji SDK
  3. nie używaj osobnego wątku

Użyj usługi lub AsyncTask

Zobacz też pytanie o przepełnienie stosu:

android.os.NetworkOnMainThreadException wysyłanie wiadomości e-mail z Androida

 61
Author: venergiac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:38

Wykonaj akcje sieciowe na innym wątku

Na Przykład:

new Thread(new Runnable(){
    @Override
    public void run() {
        // Do network action in this function
    }
}).start();

I dodaj to do AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/>
 53
Author: henry4343,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-13 19:49:55

Wyłączasz tryb ścisły używając następującego kodu:

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

Nie jest to zalecane : Użyj interfejsu AsyncTask.

Pełny kod dla obu metod

 48
Author: Sandeep,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-20 09:04:29

Operacje sieciowe nie mogą być uruchamiane w głównym wątku. Musisz uruchomić wszystkie zadania sieciowe w wątku podrzędnym lub zaimplementować AsyncTask.

Tak uruchamiasz zadanie w wątku potomnym:

new Thread(new Runnable(){
    @Override
    public void run() {
        try {
            // Your implementation goes here
        } 
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}).start();
 40
Author: Dhruv Jindal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 21:08:38

Wpisz swój kod w środku:

new Thread(new Runnable(){
    @Override
    public void run() {
        try {
            // Your implementation
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}).start();

Lub:

class DemoTask extends AsyncTask<Void, Void, Void> {

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

    protected void onPostExecute(Void result) {
        // TODO: do something with the feed
    }
}
 39
Author: Vaishali Sutariya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 21:13:15

Użycie adnotacji Androida {[3] } jest opcją. Pozwoli Ci to po prostu uruchomić dowolną metodę w wątku w tle:

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

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

Zauważ, że chociaż zapewnia zalety prostoty i czytelności, ma swoje wady.

 37
Author: Oleksiy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-30 16:46:11

To się dzieje w Androidzie 3.0 i nowszych. Od Androida 3.0 i nowszych, mają ograniczone korzystanie z operacji sieciowych (funkcje, które uzyskują dostęp do Internetu) od uruchomienia w głównym wątku / wątku UI (co powstaje z Twoich metod on create i on CV w aktywności).

Ma to zachęcić do używania oddzielnych wątków do operacji sieciowych. Zobacz AsyncTask Aby uzyskać więcej informacji na temat prawidłowego wykonywania działań sieciowych.

 36
Author: raihan ahmed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-09 16:27:30

Nie powinieneś wykonywać żadnych czasochłonnych zadań na głównym wątku (wątku UI), takich jak operacje sieciowe, wejścia/wyjścia plików lub operacje bazy danych SQLite. Tak więc w przypadku tego rodzaju operacji należy utworzyć wątek roboczy, ale problem polega na tym, że nie można bezpośrednio wykonać żadnej operacji związanej z interfejsem użytkownika z wątku roboczego. W tym celu należy użyć Handler i przekazać Message.

Aby uprościć te wszystkie rzeczy, Android zapewnia różne sposoby, takie jak AsyncTask, AsyncTaskLoader, CursorLoader lub IntentService. Więc możesz użyć dowolnego z nich zgodnie z Twoimi wymaganiami.

 32
Author: Kapil Vats,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-09 16:29:41

[[4]}top odpowiedź spektom działa idealnie.

Jeśli piszesz AsyncTask inline i nie rozszerzasz jako klasa, a ponadto, jeśli istnieje potrzeba uzyskania odpowiedzi z AsyncTask, można użyć metody get(), Jak Poniżej.

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

(z jego przykładu.)

 31
Author: sivag1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:29

Błąd jest spowodowany wykonywaniem długich operacji w głównym wątku,możesz łatwo naprawić problem za pomocą Asyntask lub Thread . Możesz sprawdzić tę bibliotekę AsyncHTTPClient dla lepszej obsługi.

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
    }
});
 31
Author: Ashwin S Ashok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-07 04:53:07

Jest to rzucane tylko dla aplikacji ukierunkowanych na plaster miodu SDK lub wyższy. Aplikacje obsługujące wcześniejsze wersje SDK mogą tworzyć sieć w swoich głównych wątkach pętli zdarzeń.

Błąd to Ostrzeżenie SDK!

 25
Author: perry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 21:09:34

Dla mnie było tak:

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

Urządzenie, na którym testowałem moją aplikację, to 4.1.2, czyli SDK w wersji 16!

Upewnij się, że wersja docelowa jest taka sama jak Biblioteka docelowa Androida. Jeśli nie jesteś pewien, jaka jest twoja docelowa biblioteka, kliknij prawym przyciskiem myszy projekt - > buduj ścieżkę -> Android, i to powinien być ten, który jest zaznaczony.

Również, jak inni wspominali, Dołącz prawidłowe uprawnienia dostępu do Internetu:

<uses-permission android:name="android.permission.INTERNET"/>
 21
Author: rharvey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 21:07:28

Po prostu wymówić coś wprost:

Główny wątek to w zasadzie wątek interfejsu użytkownika.

Więc mówienie, że nie możesz wykonywać operacji sieciowych w głównym wątku oznacza, że nie możesz wykonywać operacji sieciowych w wątku UI, co oznacza, że nie możesz wykonywać operacji sieciowych w bloku *runOnUiThread(new Runnable() { ... }* wewnątrz innego wątku.

(po prostu miałem długą chwilę drapania głową próbując dowiedzieć się, dlaczego dostaję ten błąd gdzieś indziej niż mój główny wątek. To dlaczego; ten wątek pomógł; i mam nadzieję, że ten komentarz pomoże komuś innemu.)

 19
Author: Novak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-24 21:32:53

Ten wyjątek występuje z powodu ciężkich zadań wykonywanych w głównym wątku, jeśli to zadanie zajmuje zbyt dużo czasu .

Aby tego uniknąć, możemy obsłużyć to za pomocą wątków lub executerów

Executors.newSingleThreadExecutor().submit(new Runnable() {
    @Override
    public void run() {
        // You can perform your task here.
    }
});
 17
Author: amardeep,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 21:12:36
    **Use like this in Your Activity**

    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 inten=new Intent(getApplicationContext(),ComposeMail.class);
            //intent.putParcelableArrayListExtra("valuesList", value);

            startActivity(inten);



                }
            }).start();
        }
    });
 13
Author: dhiraj kakran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-01 13:43:59

W prostych słowach,

NIE WYKONUJ PRACY SIECIOWEJ W WĄTKU UI

Na przykład, jeśli wykonasz żądanie HTTP, jest to akcja sieciowa.

Rozwiązanie:

  1. musisz utworzyć nowy wątek
  2. lub użyj klasy AsyncTask

Sposób:

Włóż wszystkie swoje prace do środka

  1. run() metoda nowego wątku
  2. lub doInBackground() Metoda AsyncTask klasy.

Ale:

Gdy otrzymasz coś z odpowiedzi sieci i chcesz pokazać to w widoku (np. wyświetl komunikat odpowiedzi w TextView), musisz wrócić z powrotem do wątku UI.

Jeśli tego nie zrobisz, dostaniesz ViewRootImpl$CalledFromWrongThreadException.

Jak?

  1. podczas korzystania z AsyncTask, Aktualizuj widok z metody onPostExecute()
  2. lub wywołanie runOnUiThread() metoda i widok aktualizacji wewnątrz metody run().
 12
Author: Nabin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:45

Istnieje wiele świetnych odpowiedzi na to pytanie, ale wiele świetnych bibliotek pojawiło się od czasu opublikowania tych odpowiedzi. Jest to swego rodzaju przewodnik dla początkujących.

Omówię kilka przypadków użycia do wykonywania operacji sieciowych i rozwiązanie lub dwa dla każdego.

Odpoczynek przez HTTP

zazwyczaj Json, może być XML lub coś innego

Pełny dostęp do API

Załóżmy, że piszesz aplikację, która pozwala użytkownikom śledzić ceny akcji, stopy procentowe i kursy walut. Znajdziesz API Json, które wygląda mniej więcej tak:

http://api.example.com/stocks                       //ResponseWrapper<String> object containing a list of Srings with ticker symbols
http://api.example.com/stocks/$symbol               //Stock object
http://api.example.com/stocks/$symbol/prices        //PriceHistory<Stock> object
http://api.example.com/currencies                   //ResponseWrapper<String> object containing a list of currency abbreviation
http://api.example.com/currencies/$currency         //Currency object
http://api.example.com/currencies/$id1/values/$id2  //PriceHistory<Currency> object comparing the prices of the first currency (id1) to the second (id2)

Modernizacja z kwadratu

Jest to doskonały wybór dla API z wieloma punktami końcowymi i pozwala zadeklarować pozostałe punkty końcowe zamiast konieczności kodowania ich indywidualnie, jak w przypadku innych bibliotek, takich jak ion lub Volley. (strona internetowa: http://square.github.io/retrofit/)

Jak to wykorzystać w finansach API?

Buduj.gradle

Dodaj te linie do buid poziomu modułu.gradle:

implementation 'com.squareup.retrofit2:retrofit:2.3.0' //retrofit library, current as of September 21, 2017
implementation 'com.squareup.retrofit2:converter-gson:2.3.0' //gson serialization and deserialization support for retrofit, version must match retrofit version

FinancesApi.java

public interface FinancesApi {
    @GET("stocks")
    Call<ResponseWrapper<String>> listStocks();
    @GET("stocks/{symbol}")
    Call<Stock> getStock(@Path("symbol")String tickerSymbol);
    @GET("stocks/{symbol}/prices")
    Call<PriceHistory<Stock>> getPriceHistory(@Path("symbol")String tickerSymbol);

    @GET("currencies")
    Call<ResponseWrapper<String>> listCurrencies();
    @GET("currencies/{symbol}")
    Call<Currency> getCurrency(@Path("symbol")String currencySymbol);
    @GET("currencies/{symbol}/values/{compare_symbol}")
    Call<PriceHistory<Currency>> getComparativeHistory(@Path("symbol")String currency, @Path("compare_symbol")String currencyToPriceAgainst);
}

FinancesApiBuilder

public class FinancesApiBuilder {
    public static FinancesApi build(String baseUrl){
        return new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
                    .create(FinancesApi.class);
    }
}

FinancesFragment snippet

FinancesApi api = FinancesApiBuilder.build("http://api.example.com/"); //trailing '/' required for predictable behavior
api.getStock("INTC").enqueue(new Callback<Stock>(){
    @Override
    public void onResponse(Call<Stock> stockCall, Response<Stock> stockResponse){
        Stock stock = stockCall.body();
        //do something with the stock
    }
    @Override
    public void onResponse(Call<Stock> stockCall, Throwable t){
        //something bad happened
    }
}

Jeśli Twoje API wymaga klucza API lub innego nagłówka, takiego jak token użytkownika itp. aby zostać wysłanym, modernizacja ułatwia to (zobacz tę niesamowitą odpowiedź po szczegóły: https://stackoverflow.com/a/42899766/1024412).

Jednorazowy dostęp do ReST API

Załóżmy, że budujesz aplikację "Pogoda nastroju", która sprawdza lokalizację GPS użytkowników i sprawdza aktualną temperaturę w tym obszarze i informuje ich o nastroju. Tego typu aplikacja nie musi deklarować punktów końcowych API; musi tylko mieć dostęp do jednego punktu końcowego API.

Ion

Jest to świetna biblioteka dla tego typu dostępu.

Proszę przeczytać msysmilu ' s great odpowiedź ( https://stackoverflow.com/a/28559884/1024412 )

Ładowanie obrazów przez HTTP

Volley

Volley może być również używany do ReST API, ale ze względu na bardziej skomplikowaną wymaganą konfigurację wolę używać Retrofit z kwadratu jak wyżej (http://square.github.io/retrofit/)

Załóżmy, że budujesz aplikację społecznościową i chcesz załadować zdjęcia profilowe znajomych.

Buduj.gradle

Dodaj ten wiersz do Twój buid poziomu modułu.gradle:

implementation 'com.android.volley:volley:1.0.0'

ImageFetch.java

Volley wymaga więcej konfiguracji niż modernizacji. Będziesz musiał utworzyć taką klasę, aby skonfigurować RequestQueue, ImageLoader i ImageCache, ale nie jest tak źle: {]}

public class ImageFetch {
    private static ImageLoader imageLoader = null;
    private static RequestQueue imageQueue = null;

    public static ImageLoader getImageLoader(Context ctx){
        if(imageLoader == null){
            if(imageQueue == null){
                imageQueue = Volley.newRequestQueue(ctx.getApplicationContext());
            }
            imageLoader = new ImageLoader(imageQueue, new ImageLoader.ImageCache() {
                Map<String, Bitmap> cache = new HashMap<String, Bitmap>();
                @Override
                public Bitmap getBitmap(String url) {
                    return cache.get(url);
                }
                @Override
                public void putBitmap(String url, Bitmap bitmap) {
                    cache.put(url, bitmap);
                }
            });
        }
        return imageLoader;
    }
}

User_view_dialog.xml

Dodaj następujący plik XML układu, aby dodać obraz:

<com.android.volley.toolbox.NetworkImageView
    android:id="@+id/profile_picture"
    android:layout_width="32dp"
    android:layout_height="32dp"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    app:srcCompat="@android:drawable/spinner_background"/>

UserViewDialog.java

Dodaj następujący kod do metody onCreate (Fragment, Activity) lub konstruktor (Dialog):

NetworkImageView profilePicture = view.findViewById(R.id.profile_picture);
profilePicture.setImageUrl("http://example.com/users/images/profile.jpg", ImageFetch.getImageLoader(getContext());

Picasso

[[9]}kolejna wspaniała biblioteka od Square. Zajrzyj na stronę, aby zobaczyć kilka świetnych przykładów: http://square.github.io/picasso/
 11
Author: KG6ZVP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-17 08:26:37

Chociaż powyżej jest ogromna pula rozwiązań, nikt nie wspomniał com.koushikdutta.ion: https://github.com/koush/ion

Jest również asynchroniczny i bardzo prosty w użyciu:

Ion.with(context)
.load("http://example.com/thing.json")
.asJsonObject()
.setCallback(new FutureCallback<JsonObject>() {
   @Override
    public void onCompleted(Exception e, JsonObject result) {
        // do stuff with the result or error
    }
});
 9
Author: msysmilu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-17 10:31:31

To działa. Tylko uprościłem odpowiedź Dr. Luiji ' ego.

new Thread() {
    @Override
    public void run() {
        try {
            //Your code goes here
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}.start();
 6
Author: Kacy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-13 23:10:17

Na Androidzie operacje sieciowe nie mogą być uruchamiane w głównym wątku. Do wykonywania operacji sieciowych można użyć wątku, AsyncTask (zadania o krótkim czasie działania), Service (zadania o długim czasie działania).

 6
Author: Ponsuyambu Velladurai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-25 09:32:51

Dostęp do zasobów sieciowych z głównego wątku (UI) powoduje ten wyjątek. Aby uzyskać dostęp do zasobów sieciowych, użyj oddzielnego wątku lub funkcji AsyncTask, aby uniknąć tego problemu.

 6
Author: RevanthKrishnaKumar V.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-25 09:35:31

RxAndroid to kolejna lepsza alternatywa dla tego problemu i oszczędza nam kłopotów z tworzeniem wątków, a następnie publikowaniem wyników w wątku interfejsu Androida. Musimy tylko określić wątki, na których mają być wykonywane zadania i wszystko jest obsługiwane wewnętrznie.

Observable<List<String>> musicShowsObservable = Observable.fromCallable(new Callable<List<String>>() { 

  @Override 
  public List<String> call() { 
    return mRestClient.getFavoriteMusicShows(); 
  }
});

mMusicShowSubscription = musicShowsObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<String>>() {

    @Override 
    public void onCompleted() { }

    @Override 
    public void onError(Throwable e) { }

    @Override 
    public void onNext(List<String> musicShows){
        listMusicShows(musicShows);
    }
});
  1. Po określeniu (Schedulers.io()), RxAndroid uruchomi getFavoriteMusicShows() w innym wątku.

  2. Używając AndroidSchedulers.mainThread() chcemy obserwować to, co obserwowalne w wątku UI, tzn. chcemy, aby nasze wywołanie zwrotne onNext() zostało wywołane NA wątek UI

 6
Author: Shinoo Goyal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-10 07:52:47

Nowe rozwiązania Threadi AsyncTask zostały już wyjaśnione.

AsyncTask idealnie nadaje się do krótkich operacji. Normal Thread nie jest korzystne dla Androida.

Spójrz na alternatywne rozwiązanie za pomocą HandlerThread i Handler

HandlerThread

Poręczna Klasa do uruchamiania nowego wątku z looperem. Looper może być następnie użyty do tworzenia klas obsługi. Zauważ, że start() musi być dzwoniłem.

Obsługa pozwala na wysyłanie i przetwarzanie wiadomości i obiektów, które można uruchomić, związanych z wiadomością w wątku. Każda instancja obsługi jest powiązana z pojedynczym wątkiem i kolejką wiadomości tego wątku. Kiedy tworzysz nową funkcję obsługi, jest ona powiązana z kolejką wątków / wiadomości wątku, który ją tworzy - od tego momentu będzie ona dostarczać wiadomości i pliki uruchamiające do tej kolejki i wykonywać je w miarę ich wychodzenia kolejki komunikatów.

Rozwiązanie:

  1. Utwórz HandlerThread

  2. Call start() on HandlerThread

  3. Utwórz Handler pobierając Looper z HanlerThread

  4. Osadzenie kodu związanego z operacjami sieciowymi w obiekcie Runnable

  5. Zgłoś Runnable zadanie do Handler

Przykładowy fragment kodu, który Adres NetworkOnMainThreadException

HandlerThread handlerThread = new HandlerThread("URLConnection");
handlerThread.start();
handler mainHandler = new Handler(handlerThread.getLooper());

Runnable myRunnable = new Runnable() {
    @Override
    public void run() {
        try {
            Log.d("Ravi", "Before IO call");
            URL page = new URL("http://www.google.com");
            StringBuffer text = new StringBuffer();
            HttpURLConnection conn = (HttpURLConnection) page.openConnection();
            conn.connect();
            InputStreamReader in = new InputStreamReader((InputStream) conn.getContent());
            BufferedReader buff = new BufferedReader(in);
            String line;
            while ( (line =  buff.readLine()) != null) {
                text.append(line + "\n");
            }
            Log.d("Ravi", "After IO call");
            Log.d("Ravi",text.toString());

        }catch( Exception err){
            err.printStackTrace();
        }
    }
};
mainHandler.post(myRunnable);

Zalety stosowania tego podejścia:

  1. Tworzenie nowego Thread/AsyncTask dla każda operacja sieciowa jest kosztowna. Thread/AsyncTask zostanie zniszczony i ponownie utworzony dla następnych operacji sieciowych. Ale przy podejściu Handler i HandlerThread, można przesyłać wiele operacji sieciowych (jako zadania uruchamialne) do pojedynczego HandlerThread za pomocą Handler.
 6
Author: Ravindra babu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-05 04:41:03

Nie możesz zaimplementować operacji sieciowych w wątku interfejsu użytkownika na Androidzie. Będziesz musiał użyć klasy AsyncTask do wykonywania operacji związanych z siecią, takich jak wysyłanie żądania API, pobieranie obrazu z adresu URL itp. korzystając z metod wywołania zwrotnego AsyncTask, możesz uzyskać wynik w onPostExecute menthod i będziesz w wątku UI i możesz wypełnić UI danymi z serwisu internetowego lub coś w tym stylu.

Przykład: załóżmy, że chcesz pobrać obraz z adresu URL: https://www.samplewebsite.com/sampleimage.jpg

Rozwiązanie przy użyciu AsyncTask: są odpowiednio.

    public class MyDownloader extends AsyncTask<String,Void,Bitmap>
    {
        @Override
        protected void onPreExecute() {
            // Show progress dialog
            super.onPreExecute();
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            //Populate Ui
            super.onPostExecute(bitmap);
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            // Open URL connection read bitmaps and return form here
            return result;
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            // Show progress update
            super.onProgressUpdate(values);
        }


    }
}

Uwaga: nie zapomnij dodać uprawnienia do Internetu w pliku manifestu Androida. Będzie działać jak urok. :)

 5
Author: Krishna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-25 09:39:03

Jest jeszcze jeden bardzo wygodny sposób rozwiązania tego problemu-użyj możliwości współbieżności rxJava. Możesz wykonać dowolne zadanie w tle i opublikować wyniki do głównego wątku w bardzo wygodny sposób, więc wyniki te zostaną przekazane do łańcucha przetwarzania.

Pierwszą zweryfikowaną odpowiedzią jest użycie AsynTask. Tak, jest to rozwiązanie, ale obecnie jest przestarzałe, ponieważ wokół są nowe narzędzia.

String getUrl() {
    return "SomeUrl";
}

private Object makeCallParseResponse(String url) {
    return null;
    //
}

private void processResponse(Object o) {

}

Metoda getUrl podaje adres URL i zostanie wykonana na głównym wątku.

MakeCallParseResponse(..)- czy faktycznie działa

ProcessResponse(..)- będzie obsługiwać wynik na głównym wątku.

Kod wykonania asynchronicznego będzie wyglądał następująco:

rx.Observable.defer(new Func0<rx.Observable<String>>() {
    @Override
    public rx.Observable<String> call() {
        return rx.Observable.just(getUrl());
    }
})
    .subscribeOn(Schedulers.io())
    .observeOn(Schedulers.io())
    .map(new Func1<String, Object>() {
        @Override
        public Object call(final String s) {
            return makeCallParseResponse(s);
        }
    })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Action1<Object>() {
        @Override
        public void call(Object o) {
             processResponse(o);
        }
    },
    new Action1<Throwable>() {
        @Override
        public void call(Throwable throwable) {
            // Process error here, it will be posted on
            // the main thread
        }
    });

W porównaniu do AsyncTask, ta metoda pozwala na przełączanie harmonogramów dowolną liczbę razy (powiedzmy, pobieranie danych z jednego harmonogramu i przetwarzanie tych danych na innym (powiedzmy, Scheduler.obliczenie ()). Możesz również zdefiniować własne harmonogramy.

Aby korzystać z tej biblioteki, Dołącz następujące linie do swojego kompilatora.plik gradle:

   compile 'io.reactivex:rxjava:1.1.5'
   compile 'io.reactivex:rxandroid:1.2.0'

Ostatnia zależność zawiera wsparcie dla .mainthread () scheduler.

Istnieje doskonały ebook dla rx-java .

 5
Author: Alex Shutov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-25 09:48:34