web-dev-qa-db-fra.com

Comment puis-je réparer Android.os.NetworkOnMainThreadException?

J'ai eu une erreur lors de l'exécution de mon projet Android pour RssReader. 

Code:

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

Et cela montre l'erreur ci-dessous:

Android.os.NetworkOnMainThreadException

Comment puis-je résoudre ce problème?

2137
bejoy george

Cette exception est levée lorsqu'une application tente d'effectuer une opération de mise en réseau sur son thread principal. Exécutez votre code dans 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
    }
}

Comment exécuter la tâche:

Dans le fichier MainActivity.Java, vous pouvez ajouter cette ligne dans votre méthode oncreate()

new RetrieveFeedTask().execute(urlToRssFeed);

N'oubliez pas d'ajouter ceci dans le fichier AndroidManifest.xml:

<uses-permission Android:name="Android.permission.INTERNET"/>
2367
michael

Vous devez presque toujours exécuter des opérations réseau sur un thread ou en tant que tâche asynchrone.

Mais est possible de supprimer cette restriction et de remplacer le comportement par défaut si vous êtes prêt à accepter les conséquences.

Ajouter:

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

StrictMode.setThreadPolicy(policy); 

Dans votre classe,

et

AJOUTEZ cette permission dans le fichier Android manifest.xml:

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

Conséquences:

Votre application (dans les zones de connexion Internet irrégulière) ne répond plus et se verrouille, l'utilisateur perçoit la lenteur et doit tuer de force, et vous risquez que le responsable de l'activité tue votre application et dis à l'utilisateur que celle-ci s'est arrêtée.

Android a quelques bons conseils sur les bonnes pratiques de programmation pour concevoir la réactivité: http://developer.Android.com/reference/Android/os/NetworkOnMainThreadException.html

636
user1169115

J'ai résolu ce problème en utilisant une nouvelle Thread.

Thread thread = new Thread(new Runnable() {

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

thread.start(); 
381
Dr.Luiji

La réponse acceptée comporte des inconvénients importants. Il est déconseillé d'utiliser AsyncTask pour la mise en réseau, sauf si vous vraiment savez ce que vous faites. Certains des inconvénients incluent:

  • Les AsyncTask créées en tant que classes internes non statiques ont une référence implicite à l'objet Activity englobant, à son contexte et à la totalité de la hiérarchie View créée par cette activité. Cette référence empêche la collecte de déchets de l'activité jusqu'à la fin du travail en arrière-plan de la tâche Async. Si la connexion de l'utilisateur est lente et/ou si le téléchargement est volumineux, ces fuites de mémoire à court terme peuvent devenir un problème - par exemple, si l'orientation change plusieurs fois (et que vous n'annulez pas les tâches en cours d'exécution), ou que l'utilisateur navigue loin de l'activité.
  • AsyncTask a différentes caractéristiques d'exécution en fonction de la plate-forme sur laquelle il s'exécute: avant le niveau 4 de l'API, AsyncTasks s'exécute en série sur un seul thread en arrière-plan; À partir des API de niveau 4 à 10, les AsyncTasks s'exécutent sur un pool de 128 threads au maximum; À partir de l'API niveau 11, AsyncTask s'exécute en série sur un seul thread en arrière-plan (sauf si vous utilisez la méthode surchargée executeOnExecutor et fournissez un autre exécuteur). Le code qui fonctionne correctement lorsqu’il est exécuté en série sur ICS peut se rompre lorsqu’il est exécuté simultanément sur Gingerbread, par exemple si vous avez des dépendances d’ordre d’exécution par inadvertance.

Si vous souhaitez éviter les fuites de mémoire à court terme, si vous avez des caractéristiques d’exécution bien définies sur toutes les plates-formes et une base permettant de créer une gestion réseau vraiment robuste, vous voudrez peut-être prendre en compte:

  1. Utiliser une bibliothèque qui fait un bon travail pour vous - il y a une comparaison intéressante des bibliothèques réseau dans cette question , ou
  2. Utilisez plutôt un Service ou IntentService, peut-être avec un PendingIntent pour renvoyer le résultat via la méthode onActivityResult de l'Activité.

Approche IntentService

Les inconvénients:

  • Plus de code et de complexité que AsyncTask, mais pas autant que vous ne le pensez
  • Les demandes seront mises en file d'attente et exécutées sur un thread d'arrière-plan unique. Vous pouvez facilement contrôler cela en remplaçant IntentService par une implémentation Service équivalente, peut-être comme celle-ci .
  • Euh, je ne peux pas penser à d'autres maintenant

Sur les côtés:

  • Evite le problème de fuite de mémoire à court terme
  • Si votre activité redémarre alors que les opérations réseau sont en cours, vous pouvez toujours recevoir le résultat du téléchargement via sa méthode onActivityResult.
  • Meilleure plate-forme que AsyncTask pour générer et réutiliser un code réseau robuste. Exemple: si vous devez effectuer un téléchargement important, vous pouvez le faire à partir de AsyncTask dans un Activity, mais si le contexte de l'utilisateur quitte l'application pour prendre un appel téléphonique, le système peut tuer le application avant la fin du téléchargement. Il est moins probable} de tuer une application avec un Service actif.
  • Si vous utilisez votre propre version simultanée de IntentService (comme celle que j'ai liée ci-dessus), vous pouvez contrôler le niveau de simultanéité via Executor.

Résumé d'implémentation

Vous pouvez implémenter un IntentService pour effectuer des téléchargements sur un seul thread en arrière-plan assez facilement.

Étape 1: Créez un IntentService pour effectuer le téléchargement. Vous pouvez lui indiquer le contenu à télécharger via Intent extra, et lui transmettre un PendingIntent à utiliser pour renvoyer le résultat au 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);
        }
    }
}

Étape 2: inscrivez le service dans le manifeste:

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

Étape 3: Appelez le service depuis l'activité en passant un objet PendingResult que le service utilisera pour renvoyer le résultat:

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

Étape 4: Gérez le résultat dans 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);
}

Un projet github contenant un projet Android/Studio complet et fonctionnel est disponible ici .

137
Stevie

Vous ne pouvez pas effectuer de réseau I/O sur le thread d'interface utilisateur sur Honeycomb . Techniquement, est possible sur les versions précédentes d’Android, mais c’est une très mauvaise idée, car votre application cessera de répondre, et le système d’exploitation risque de tuer votre application parce qu’elle se comporte mal. Vous devrez exécuter un processus en arrière-plan ou utiliser AsyncTask pour effectuer votre transaction réseau sur un thread en arrière-plan.

Il existe un article sur Indolore Threading sur le site du développeur Android, qui est une bonne introduction à cela, et il vous fournira une profondeur de réponse bien meilleure que celle qui peut être fournie de manière réaliste ici.

135
Mark Allison
  1. Ne pas utiliser strictMode (uniquement en mode débogage)
  2. Ne changez pas la version du SDK
  3. Ne pas utiliser un fil séparé

Utiliser un service ou une tâche asynchrone

Voir aussi la question du débordement de pile:

Android.os.NetworkOnMainThreadException envoyer un email d'Android

67
venergiac

Faire les actions du réseau sur un autre thread

Par exemple:

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

Et ajoutez ceci à AndroidManifest.xml 

<uses-permission Android:name="Android.permission.INTERNET"/>
61
henry4343

Vous désactivez le mode strict en utilisant le code suivant:

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

Ceci n'est pas recommandé: utilisez l'interface AsyncTask.

Code complet pour les deux méthodes

52
Sandeep

Les opérations basées sur le réseau ne peuvent pas être exécutées sur le thread principal. Vous devez exécuter toutes les tâches réseau sur un thread enfant ou implémenter AsyncTask.

Voici comment vous exécutez une tâche dans un thread enfant:

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

Mettez votre code à l'intérieur:

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

Ou:

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
    }
}
43
Vaishali Sutariya

Utiliser Annotations Android est une option. Cela vous permettra d’exécuter simplement n’importe quelle méthode dans un fil d’arrière-plan:

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

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

Notez que, bien qu’il offre des avantages de simplicité et de lisibilité, il présente des inconvénients. 

40
Oleksiy

Cela se produit dans Android 3.0 et supérieur. À partir d'Android 3.0 ou ultérieur, ils ont restreint l'utilisation des opérations réseau (fonctions qui accèdent à Internet) dans le thread principal/thread d'interface utilisateur (ce qui est généré par vos méthodes de création et de reprise dans l'activité).

Ceci encourage l'utilisation de threads distincts pour les opérations réseau. Voir AsyncTask pour plus de détails sur la manière d’exécuter correctement les activités du réseau.

39
raihan ahmed

Vous ne devez effectuer aucune tâche fastidieuse sur le thread principal (thread d'interface utilisateur), comme toute opération de réseau, d'entrée-sortie de fichier ou d'opération de base de données SQLite. Donc, pour ce type d'opération, vous devez créer un thread de travail, mais le problème est que vous ne pouvez pas effectuer directement d'opération liée à l'interface utilisateur à partir de votre thread de travail. Pour cela, vous devez utiliser Handler et passer le Message

Pour simplifier toutes ces choses, Android propose différentes méthodes, telles que AsyncTask, AsyncTaskLoader, CursorLoader ou IntentService. Vous pouvez donc utiliser ces options en fonction de vos besoins.

35
Kapil Vats

L'erreur est due à l'exécution de longues opérations dans le thread principal. Vous pouvez facilement résoudre le problème en utilisant AsynTask ou Thread . Vous pouvez extraire cette bibliothèque AsyncHTTPClient pour une meilleure gestion. 

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
    }
});
34
Ashwin S Ashok

Le top réponse de spektom fonctionne parfaitement.

Si vous écrivez le AsyncTask inline et ne prolongez pas en tant que classe, et s'il est nécessaire d'obtenir une réponse de la AsyncTask, vous pouvez utiliser la méthode get() comme ci-dessous.

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

(De son exemple.)

34
sivag1

Ceci n'est émis que pour les applications ciblant le Honeycomb SDK ou une version ultérieure. Les applications ciblant des versions antérieures du SDK sont autorisées à mettre en réseau leurs threads de boucle d'événements principaux.

L'erreur est l'avertissement du SDK!

28
perry

Pour moi c'était ça:

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

L'appareil sur lequel je testais mon application était la version 4.1.2, qui correspond à la version 16 du SDK!

Assurez-vous que la version cible est la même que votre bibliothèque cible Android. Si vous ne savez pas quelle est votre bibliothèque cible, cliquez avec le bouton droit de la souris sur votre projet -> Chemin de construction -> Android , et vous devriez sélectionner celui qui est coché.

En outre, comme d'autres l'ont mentionné, incluez les autorisations appropriées pour accéder à Internet:

<uses-permission Android:name="Android.permission.INTERNET"/>
23
rharvey

Juste pour épeler quelque chose de manière explicite:

Le fil principal est essentiellement le fil de l'interface utilisateur.

Dire que vous ne pouvez pas effectuer d'opérations de réseau dans le thread principal signifie que vous ne pouvez pas effectuer d'opérations de réseau dans le thread d'interface utilisateur, ce qui signifie que vous ne pouvez pas effectuer d'opérations de réseau dans un bloc *runOnUiThread(new Runnable() { ... }* dans un autre thread.

(J'ai juste eu un long moment de réflexion en essayant de comprendre pourquoi j'avais cette erreur ailleurs que dans mon fil principal. C'est pourquoi; ce fil a aidé; et j'espère que ce commentaire aidera quelqu'un d'autre.)

21
Novak

Cette exception est due à une tâche lourde effectuée sur le thread principal si cette tâche d'exécution prend trop de temps.

Pour éviter cela, nous pouvons le gérer en utilisant threads ou executers

Executors.newSingleThreadExecutor().submit(new Runnable() {
    @Override
    public void run() {
        // You can perform your task here.
    }
});
19
amardeep

Utilisez ceci dans votre activité

    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();
        }
    });
15
dhiraj kakran

En des mots simples,

NE TRAVAILLEZ PAS EN RESEAU DANS LE FIL D'UI

Par exemple, si vous faites une requête HTTP, il s’agit d’une action réseau.

Solution:

  1. Vous devez créer un nouveau fil
  2. Ou utiliser Classe AsyncTask

Façon:

Mettez toutes vos oeuvres à l'intérieur

  1. run() méthode du nouveau thread
  2. OudoInBackground() méthode de la classe AsyncTask.

Mais:

Lorsque vous recevez quelque chose de la réponse du réseau et que vous souhaitez l'afficher dans votre vue (comme un message de réponse affiché dans TextView), vous devez revenir au thread UI.

Si vous ne le faites pas, vous obtiendrez ViewRootImpl$CalledFromWrongThreadException.

Comment?

  1. Lorsque vous utilisez AsyncTask, mettez à jour la vue à partir de la méthode onPostExecute()
  2. Ou appelez runOnUiThread() méthode et mettez à jour la vue dans la méthode run().
14
Nabin

Il y a déjà beaucoup de bonnes réponses à cette question, mais beaucoup de bonnes bibliothèques ont été publiées depuis leur publication. Ceci est conçu comme une sorte de guide débutant.

Je couvrirai plusieurs cas d’utilisation pour effectuer des opérations sur le réseau et a solution ou deux pour chacun.

ReST sur HTTP

_ {Typiquement Json, peut être XML ou autre chose)

Accès complet à l'API

Supposons que vous écriviez une application qui permet aux utilisateurs de suivre les cours des actions, les taux d’intérêt et les taux de change actuels. Vous trouvez une API Json qui ressemble à ceci:

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)

Retrofit de Square

C'est un excellent choix pour une API avec plusieurs noeuds finaux et vous permet de déclarer les noeuds finaux ReST au lieu d'avoir à les coder individuellement comme avec d'autres bibliothèques comme ion ou Volley. (site web: http://square.github.io/retrofit/ )

Comment l'utilisez-vous avec l'API Finances?

build.gradle

Ajoutez ces lignes à votre buid.gradle de niveau Module:

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

Extrait de fragment de Finances

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
    }
}

Si votre API nécessite l'envoi d'une clé API ou d'un autre en-tête, tel qu'un jeton d'utilisateur, etc., Retrofit facilite les choses (voir cette réponse géniale pour plus de détails: https://stackoverflow.com/a/42899766/ 1024412 ).

Accès unique à l'API ReST

Supposons que vous construisez une application «météo d'humeur» qui recherche la position GPS des utilisateurs, vérifie la température actuelle dans cette zone et leur indique l'ambiance. Ce type d'application n'a pas besoin de déclarer les points de terminaison de l'API; il doit simplement pouvoir accéder à un point de terminaison d'API.

Ion

C'est une excellente bibliothèque pour ce type d'accès.

Veuillez lire l'excellente réponse de msysmilu ( https://stackoverflow.com/a/28559884/1024412 )

Charger des images via HTTP

Volée

Volley peut également être utilisé pour les API ReST, mais en raison de la configuration plus complexe requise, je préfère utiliser Retrofit from Square comme ci-dessus ( http://square.github.io/retrofit/ )

Supposons que vous construisez une application de réseau social et que vous souhaitez charger les photos de profil d'amis.

build.gradle

Ajoutez cette ligne à votre buid.gradle de niveau module:

implementation 'com.Android.volley:volley:1.0.0'

ImageFetch.Java

Volley nécessite plus de configuration que Retrofit. Vous devrez créer une classe comme celle-ci pour configurer un RequestQueue, un ImageLoader et un ImageCache, mais ce n'est pas si grave:

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

Ajoutez les éléments suivants à votre fichier XML de mise en page pour ajouter une image:

<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

Ajoutez le code suivant à la méthode onCreate (Fragment, Activity) ou au constructeur (Dialog):

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

Picasso

Une autre excellente bibliothèque de Square. Veuillez consulter le site pour quelques exemples intéressants: http://square.github.io/picasso/

12
KG6ZVP

Bien que ci-dessus, il existe un énorme pool de solutions, personne n’a mentionné com.koushikdutta.ion: https://github.com/koush/ion

C'est aussi asynchrone et très simple à utiliser:

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
    }
});
10
msysmilu

Les nouvelles solutions Thread et AsyncTask ont déjà été expliquées.

AsyncTask devrait idéalement être utilisé pour de courtes opérations. Thread normal n'est pas préférable pour Android. 

Découvrez une autre solution utilisant HandlerThread et Handler

HandlerThread

Classe pratique pour démarrer un nouveau thread qui a une boucle. Le boucleur peut ensuite être utilisé pour créer des classes de gestionnaires. Notez que start() doit toujours être appelé.

Gestionnaire:

Un gestionnaire vous permet d’envoyer et de traiter les objets Message et Runnable associés au MessageQueue d’un thread. Chaque instance de gestionnaire est associée à un seul thread et à la file de messages de ce thread. Lorsque vous créez un nouveau gestionnaire, il est lié au thread/à la file d'attente de messages du thread qui le crée - à partir de ce moment, il distribuera les messages et les exécutables à cette file d'attente et les exécutera au fur et à mesure qu'ils sortent du message. queue.

Solution:

  1. Créer HandlerThread

  2. Appelez start() au HandlerThread

  3. Créez Handler en obtenant Looper à partir de HanlerThread

  4. Incorporez le code associé à votre opération réseau dans l'objet Runnable

  5. Soumettez la tâche Runnable à Handler

Exemple d'extrait de code portant l'adresse 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);

Avantages d'utiliser cette approche:

  1. Créer un nouveau Thread/AsyncTask pour chaque opération de réseau coûte cher. Le Thread/AsyncTask sera détruit et recréé pour les prochaines opérations sur le réseau. Toutefois, avec les approches Handler et HandlerThread, vous pouvez soumettre de nombreuses opérations réseau (en tant que tâches exécutables) à une seule variable HandlerThread en utilisant Handler
8
Ravindra babu

L'accès aux ressources réseau à partir du thread principal (UI) est à l'origine de cette exception. Utilisez un thread séparé ou AsyncTask pour accéder à une ressource réseau afin d'éviter ce problème.

7

Sur Android, les opérations réseau ne peuvent pas être exécutées sur le thread principal. Vous pouvez utiliser Thread, AsyncTask (tâches à exécution courte), Service (tâches à exécution longue) pour effectuer des opérations réseau.

7

Cela marche. Je viens de simplifier un peu la réponse de Dr.Luiji.

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

RxAndroid est une autre meilleure solution à ce problème et nous évite les tracas liés à la création de threads, puis à la publication des résultats sur un thread Android UI .

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. En spécifiant (Schedulers.io()), RxAndroid exécutera getFavoriteMusicShows() sur un autre thread.

  2. En utilisant AndroidSchedulers.mainThread(), nous souhaitons observer cet observable sur le thread d'interface utilisateur, c'est-à-dire que nous souhaitons que notre rappel onNext() soit appelé sur le thread d'interface utilisateur.

7
Shinoo Goyal

Vous pouvez déplacer une partie de votre code dans un autre thread pour décharger le main thread et éviter d’obtenir ANR , NetworkOnMainThreadException , IllegalStateException (par exemple, ne peut pas accéder à la base de données sur le thread principal car potentiellement verrouiller l’UI pendant une longue période). 

Certaines approches à choisir dépendent de la situation.

Java Thread ou Android HandlerThread

Les threads Java sont à usage unique et meurent après l'exécution de la méthode d'exécution.

HandlerThread est une classe pratique pour démarrer un nouveau thread avec une boucle.

AsyncTask

AsyncTask est conçu pour être une classe d'assistance autour de Thread et Handler et ne constitue pas un framework de thread générique. AsyncTasks devrait idéalement être utilisé pour des opérations courtes (quelques secondes au maximum). Si vous devez maintenir les threads en cours d'exécution pendant de longues périodes, il est vivement recommandé d'utiliser les différentes API fournies par le package Java.util.concurrent, telles que Executor, ThreadPoolExecutor et FutureTask.

Implémentation de pool de threads ThreadPoolExecutor , ScheduledThreadPoolExecutor ...

Classe ThreadPoolExecutor qui implémente ExecutorService qui donne un contrôle précis sur le pool de threads (par exemple, taille du pool principal, taille maximale du pool, durée de conservation, etc.)

ScheduledThreadPoolExecutor - une classe qui étend ThreadPoolExecutor. Il peut planifier des tâches après un délai donné ou périodiquement.

FutureTask

FutureTask effectue un traitement asynchrone. Toutefois, si le résultat n'est pas encore prêt ou si le traitement n'est pas terminé, l'appel de get () bloquera le thread. 

AsyncTaskLoaders

AsyncTaskLoaders car ils résolvent beaucoup de problèmes inhérents à AsyncTask

IntentService

C'est le choix de fait pour le traitement de longue durée sur Android, un bon exemple serait de télécharger ou de télécharger des fichiers volumineux. Le téléchargement et le téléchargement peuvent continuer même si l'utilisateur quitte l'application et vous ne souhaitez certainement pas l'empêcher de pouvoir utiliser l'application pendant l'exécution de ces tâches.

JobScheduler

Effectivement, vous devez créer un service et créer un travail à l'aide de JobInfo.Builder qui spécifie vos critères pour savoir quand exécuter le service.

RxJava

Bibliothèque permettant de composer des programmes asynchrones et basés sur des événements en utilisant des séquences observables.

Coroutines (Kotlin)

L’essentiel est que le code asynchrone ressemble tellement à un code synchrone.

Lire la suite ici:
8 façons de faire un traitement asynchrone dans Android et compter
L’évolution de l’accès au réseau Android
Utilisation d'un pool de threads sous Android

6
yoAlex5

Vous n'êtes pas autorisé à implémenter des opérations réseau sur le thread d'interface utilisateur sous Android. Vous devrez utiliser la classe AsyncTask pour effectuer des opérations liées au réseau, telles que l'envoi d'une demande d'API, le téléchargement d'une image à partir d'une URL, etc. et en utilisant les méthodes de rappel d'AsyncTask, vous pouvez obtenir le résultat de la méthode onPostExecute et vous serez dans le fil de l'interface utilisateur. peut peupler l'interface utilisateur avec des données de service Web ou quelque chose comme ça.

Exemple: supposons que vous vouliez télécharger une image depuis une URL: https://www.samplewebsite.com/sampleimage.jpg

Solution utilisant AsyncTask: sont respectivement.

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


    }
}

Remarque: N'oubliez pas d'ajouter l'autorisation Internet dans le fichier manifeste Android. Cela fonctionnera comme un charme. :)

6
Krishna

Il existe un autre moyen très pratique de résoudre ce problème - utilisez les fonctionnalités de simultanéité de rxJava. Vous pouvez exécuter n'importe quelle tâche en arrière-plan et publier les résultats sur le thread principal de manière très pratique. Ces résultats seront donc transmis à la chaîne de traitement.

Le premier conseil de réponse vérifié consiste à utiliser AsynTask. Oui, c'est une solution, mais elle est obsolète de nos jours, car il existe de nouveaux outils.

String getUrl() {
    return "SomeUrl";
}

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

private void processResponse(Object o) {

}

La méthode getUrl fournit l'adresse URL et sera exécutée sur le thread principal.

makeCallParseResponse (..) - effectue un travail réel

processResponse (..) - gérera le résultat sur le thread principal.

Le code pour l'exécution asynchrone ressemblera à ceci:

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

Comparée à AsyncTask, cette méthode permet de changer de planificateur un nombre arbitraire de fois (par exemple, récupérer des données sur un planificateur et traiter ces données sur un autre (par exemple, Scheduler.computation ()). Vous pouvez également définir vos propres planificateurs.

Pour utiliser cette bibliothèque, incluez les lignes suivantes dans votre fichier build.gradle:

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

La dernière dépendance inclut la prise en charge du planificateur .mainThread ().

Il y a un excellent ebook pour rx-Java .

6
Alex Shutov

Vous pouvez soit utiliser KOTLIN et ANKO

Kotlin est la nouvelle langue officielle de Android vous en trouverez plus ici https://kotlinlang.org/docs/tutorials/kotlin-Android.html

Anko bibliothèque prise en charge pour Kotlin dans Android, certains documents ici https://github.com/Kotlin/anko

La solution qui est vraiment utile et ne contient que quelques lignes de code écrites par @AntonioLeiva https://antonioleiva.com/anko-background-kotlin-Android/

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

NetworkOnMainThread survient lorsque vous exécutez un travail en arrière-plan sur UI Thread; vous devez donc exécuter votre longTask job en arrière-plan. Vous pouvez le faire en utilisant cette méthode et Kotlin avec Anko dans votre application Android.

5
J.D.1731

J'ai résolu ce problème d'une manière simple ...

J'ai ajouté après oncreateStrictMode.enableDefaults(); et résolu ceci.

Ou

utilisez Service ou AsyncTask pour résoudre ce problème

Remarque:

Do not change SDK version
Do not use a separate thread

Pour plus, vérifiez ceci .

4
Subhalaxmi Nayak

Cette exception est levée lorsqu'une application tente d'effectuer une opération de mise en réseau sur son thread principal . Si votre tâche a duré plus de cinq secondes, la fermeture est forcée.

Exécutez votre code dans AsyncTask:

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

    protected RSSFeed doInBackground(String... urls) {
       // TODO: Connect
    }

    protected void onPostExecute(RSSFeed feed) {
        // TODO: Check this.exception
        // TODO: Do something with the feed
    }
}
4
Adnan Abdollah Zaki

Android.os.NetworkOnMainThreadException est levé lorsque des opérations réseau sont effectuées sur le thread principal. Vous feriez mieux de faire cela dans AsyncTask pour supprimer cette exception. Écris-le comme ceci:

    new AsyncTask<Void,String,String>(){

        @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();
}
3
Mansuu....

Nous pouvons également utiliser RxJava pour déplacer les opérations du réseau vers un fil d’arrière-plan. Et c'est assez simple aussi.

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

Vous pouvez faire beaucoup plus de choses avec RxJava.Voici quelques liens pour RxJava. N'hésitez pas à creuser. 

Tâche RxJava Async sous Android

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

3
bpr10

Le thread principal est le thread d'interface utilisateur et vous ne pouvez pas effectuer d'opération dans le thread principal susceptible de bloquer l'interaction de l'utilisateur. Vous pouvez résoudre ce problème de deux manières:

Forcer à faire la tâche dans le fil principal comme ceci

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

Ou créez un gestionnaire simple et mettez à jour le thread principal si vous le souhaitez.

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

Et pour arrêter le fil, utilisez:

newHandler.removeCallbacks(runnable);

Pour plus d’informations, consultez ceci: Filetage sans effort

3
Anonymous

Vous pouvez également résoudre ce problème en utilisant le mode strict en utilisant le code ci-dessous. C'est aussi une alternative à la résolution de ce problème.

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

Mais la meilleure pratique serait d'utiliser AsyncTask.

3
Himanshu

Comment réparer Android.os.NetworkOnMainThreadException

Qu'est-ce que NetworkOnMainThreadException:

Dans Android, toutes les opérations de l'interface utilisateur doivent être effectuées sur le fil de l'interface utilisateur (fil principal). Si nous effectuons des opérations en arrière-plan ou une opération du réseau sur le thread principal, nous risquons que cette exception se produise et que l'application ne réponde pas.

Comment le réparer:

Pour éviter ce problème, vous devez utiliser un autre thread pour les opérations en arrière-plan ou les opérations réseau, comme utiliser asyncTask et utiliser une bibliothèque pour les opérations réseau telles que Volley, AsyncHttp, etc.

3

L'exception NetworkOnMainThread se produit car vous avez appelé une opération de réseau sur le thread par défaut, c'est-à-dire le thread d'interface utilisateur. Selon la version Android Android 3 (Honeycomb) qui n’est pas autorisé, vous devez appeler une opération réseau en dehors du thread principal.

Vous pouvez utiliser AsyncTask, IntentService ou créer votre propre thread et appel à l'intérieur de la méthode d'exécution . Pour plus d'informations, visitez la page Connexion au réseau.

1
BalaramNayak

Faites ceci en arrière-plan en utilisant 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
    }
}

Appelle où tu as besoin

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
    }
}

Appeler à Kotlin

MyNetworkTask().execute(url)
1
Vipul Prajapati

Vous ne pouvez pas appeler le réseau sur le thread principal ou le thread UI. Sur Android, si vous souhaitez appeler le réseau, il existe deux options:

  1. Appelez asynctask, qui exécutera un thread d'arrière-plan pour gérer l'opération réseau.
  2. Vous pouvez créer votre propre thread exécutable pour gérer le fonctionnement du réseau.

Personnellement je préfère asynctask. Pour plus d'informations, vous pouvez consulter ce lien .

1
Hossain Ahamed

Comme Android travaille sur un seul thread, vous ne devez effectuer aucune opération de réseau sur le thread principal. Il y a plusieurs façons d'éviter cela.

Utilisez la méthode suivante pour effectuer une opération réseau

  • Asysnctask : Pour les petites opérations qui ne prennent pas beaucoup de temps.
  • Intent Service : Pour le fonctionnement du réseau qui prend beaucoup de temps.
  • Utilisez une bibliothèque personnalisée telle que Volley et Retrofit pour gérer les opérations réseau complexes

N'utilisez jamais StrictMode.setThreadPolicy (policy) , car cela gèlera votre interface utilisateur et ce n'est pas du tout une bonne idée.

1
aks

Vous pouvez réellement commencer un nouveau sujet, j'avais déjà ce problème et je l'ai résolu de cette façon.

1
rObOtAndChalie

Version 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
    }
}

Exemple d'appel,

RetrieveFeedTask().execute(url)
0

Vous pouvez utiliser Kotlin-coroutines

 class YoutActivity : AppCompatActivity, CoroutineScope {

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

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

 } 

Vous pouvez suivre ce guide. 

0
Santanu Sur

J'ai eu un problème similaire, je viens d'utiliser ce qui suit dans la méthode de création de votre activité.

//allow strict mode
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

et cela a bien fonctionné.

0
Richard Kamere

À compter de 2018, je recommanderais d'utiliser RxJava dans Kotlin pour la récupération réseau. Un exemple simple est ci-dessous.

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) 
    }
0
Elye

Différentes options:

  1. utiliser un thread exécutable Java normal pour traiter une tâche réseau et peut utiliser runOnUIThread () pour mettre à jour l'interface utilisateur

  2. la tâche intentservice/async peut être utilisée si vous souhaitez mettre à jour l'interface utilisateur après avoir obtenu une réponse du réseau.

0
Ashok Kumar

Ne travaillez jamais longtemps sur le fil de l'interface utilisateur, ce travail peut être communication avec serveur, lecture/écriture sur fichier, etc. Ces tâches doivent être sur un fil d'arrière-plan, c'est pourquoi Service, AsyncTask, Threads a été créé. Vous pouvez désactiver StrictMode pour éviter un blocage mais jamais recommandé. 

Je vous suggère de tirer parti de StrictMode au moins en mode débogage. Utilisez le code ci-dessous pour obtenir les journaux de tout problème susceptible de ralentir votre application sur le fil principal.

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
            .detectAll()
            .penaltyLog()
            .build());

Vous pouvez définir différentes pénalités - 

penaltyLog() // to print log
penaltyDeath() // This will crash you App(so costly penalty)
penaltyDialog() // Show alert when something went lazy on Main thread

Il y a tellement de choses sur https://developer.Android.com/reference/Android/os/StrictMode.html

0
Rahul

Si vous travaillez dans Kotlin et Anko, vous pouvez ajouter 

 doAsync {
   method()
}
0
Devix