2016-07-01 13 views
1

Hintergrund auf separaten Thread ausgeführt wird:ANR mit Code

Diese App ist ein einfacher Wireless-LAN-Manager, Sammeln/Scannen und Anzeigen von Ergebnissen in einer Listenansicht. Da dieser Scan nach einem Intervall abläuft, habe ich einen Thread erstellt und ein Thread.sleep (Intervall) zwischen den Scans festgelegt, sodass nach Abschluss der Verarbeitung X Millisekunden verbleiben.

Ich habe ein paar "Veränderungen"/Aktuelles zu meinen Code gemacht, jetzt meine App geht in einen ANR Zustand mit einem Debugger Nachricht "Signal Catcher"]: reacting to signal 3

Full Error:

07-01 10:14:16.772 10027-10034/com.cynetstudios.wifimanager I/art: Thread[2,tid=10034,WaitingInMainSignalCatcherLoop,Thread*=0xa9007000,peer=0x12d1a0a0,"Signal Catcher"]: reacting to signal 3 
07-01 10:14:17.101 10027-10034/com.cynetstudios.wifimanager I/art: Wrote stack traces to '/data/anr/traces.txt' 

Problem:

Bevor Berechtigungen hinzugefügt:

In der onCreate() von main, hatte ich meinen Code, um meine Scan-Schleife zu starten und die Ausgabe von Daten zu starten, dies funktionierte und gab Daten wie erwartet aus.

Thema Code:

t = new Thread(new Runnable() { 
     public void run() { 
      while (!bStopThread) { 
       ThreadCounter++; 

       if (bSafe) { 
        initWiFiArrays(); //Scans and inserts data into lists 
        CreateSetAdapter(); //Converts lists into adapter, and sets adapter to ExpandableListView 
        threadRefresh.setText("# Refreshed Times : " + String.valueOf(ThreadCounter)); 
        writeResultsToFile(); //Write results to file 
       } else 
        stopScan(); 

       try { 
        Thread.sleep(scanInterval); 
       } catch (Exception x) { 
        x.printStackTrace(); 
       } 
      } 
     } 
    }); 
    t.start(); 

Nach Berechtigungen hinzugefügt:

Nach einigen Recherchen habe ich entdeckt, dass ich da es blockiert alle Thread ruft diese Initiate scan Methode aus onCreate entfernen sollte, ich hat es zu onStart hinzugefügt und eine Methode RunOnUITHD(Runnable r) hinzugefügt, die nur auf die Benutzeroberfläche zugreift, um sie mit dem notwendigen Code zu aktualisieren.

Neues Thema Code: handler = new Handler(context.getMainLooper());

RunOnUITHD

private void RunOnUITHD(Runnable runnable) { 
    handler.post(runnable); 
} 

Ich bin immer noch ANR bekommen (latest ANR Traces) und ich bin aus:

 t = new Thread(new Runnable() { 
     public void run() { 
      while (!bStopThread) { 
       ThreadCounter++; 

       if (bSafe) { 
        initWiFiArrays(); 
        CreateSetAdapter(); 
        RunOnUITHD(new Runnable() { 
         @Override 
         public void run() { 
          threadRefresh.setText("# Refreshed Times : " + String.valueOf(ThreadCounter)); 
         } 
        }); 
        writeResultsToFile(); 
       } else 
        stopScan(); 

       try { 
        Thread.sleep(scanInterval); 
       } catch (Exception x) { 
        x.printStackTrace(); 
       } 
      } 
     } 
    }); 
    t.start(); 

Handler ist definiert durch Idee, ich habe keine Ahnung, was ich falsch mache.

UPDATE:

ich jeden Teil des Haupt-Thread-Code protokolliert, es wie erwartet läuft, Looping und Schlafen, aber UI aktualisiert nicht ...

Logging Code zum Hinzufügen von new Runnable() Ich merke folgendes:

Hinzufügen eines Breakpoints zum ThreadCounter von zB ThreadCounter==11 sollte 10 "Updaing Thread ..." und "Finished update ..." Schleifen ergeben, wie aus dem Code unten ersichtlich.

RunOnUITHD(new Runnable() { 
    @Override 
    public void run() { 
     logm("POST HANDLER: updating Thread Refresh Text"); 
     threadRefresh.setText("# Refreshed Times : " + String.valueOf(ThreadCounter)); 
     logm("POST HANDLER: Finished update Thread Refresh Text"); 
    } 
}); 

Stattdessen notiere ich nur 4 Schleifen, die im Protokoll angezeigt werden.

Weitere Tests werden ausgeführt, ThreadCounter==3, Loops protokolliert = 1, alle weiteren Tests führen zu 1 protokollierten Schleife von Updating setText.

Da dieser Thread über eine benutzerdefinierte Methode von checkPermissions() in meinem @Override onStart() initiiert wird, zeige ich einen Toast Nachricht, gefolgt von den checkPermissions

@Override 
protected void onStart() { 
    super.onStart(); 
    Toast.makeText(main.this, "Starting Service", Toast.LENGTH_SHORT).show(); 
    logm("checking permissions in 'onStart'"); 
    checkPermissions(); 
} 

thoughout dieser Tests, die Toast Nachricht zeigt (nicht verschwindet) und Die setText-Updates auf 1 Schleife, was bedeutet, dass die threadRefresh TextView den folgenden Text enthält: "# Refreshed Times: 1"

Antwort

0

Es stellte sich heraus, dass ich keine Deadlock hatte, war es aufgrund einer schlechten Wahl in Intents.

Ursache:

Was ich verwendete, war ein Intent. Dies erstellt einen Dienst, der eine PendingIntent erstellt (für den Klick auf Benachrichtigung, um App erneut zu öffnen), dies gesperrt meine UIhread. SO nichts in meinem Code oben beeinflusst/verursacht das Problem!

Wie ich dieses Problem gelöst:

Verwendung Protokolle. Nicht Benutzerdefinierte definiert Protokolle, nur einfache Log.i()

angemeldet ich jeden Teil meines Code:

  1. auf hohem Niveau Anfahren und arbeitete auf eine mögliche Ursache nach unten.

  2. Wenn das nicht funktioniert/Ergebnisse produzieren, sehen Sie, ob Sie andere Klassen haben, in meinem Fall eine ServiceClass, protokollieren Sie das.

Dies ist, wo ich meinen Code gefunden weiter nicht ausführen, zu dem anrufenden Code Tracing so zurück, entdeckte ich, dass ich eine Absicht verwendet, die für die Absicht wartet bis zum Ende auf, bevor er, so meinen Code verursacht zu aufhängen.

Lösung:

verwendet haben, sollten Sie eines von 2 Arten von Intents ist für Dienste gemeint.

Diese sind Objekte häufig gefragt und gut dokumentiert. Es gibt viele Fragen auf Stackoverflow in Bezug auf die Differenz zwischen diesen zwei Typen Absicht, here und here sind 2 hoch bewertete Fragen und ein wenig UI and service Question

Ich werde eine IntentService werden.

Hoffe, das hilft!

Verwandte Themen