2012-03-16 4 views
8

ho un NetworkOnMainThreadException quando cerco di implementare il seguente codice:NetworkOnMainThread

public class HandlingXMLStuff extends ListActivity{ 
static final String URL = "xml_file"; 

static final String ITEM = "item"; //parent 
    static final String Id = "id"; 
    static final String Name = "name"; 
    static final String Desc = "desc"; 
    static final String Link = "Link"; 

@Override 
public void onCreate(Bundle savedInstanceState){ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.xmllist); 

ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>(); 

xmlparser parser = new xmlparser(); 
String xml = parser.getXmlFromUrl(URL); 
Document doc = parser.getDomElement(xml); 


NodeList nl = doc.getElementsByTagName(ITEM); 


//START: loop through all item nodes <item> 
for (int i = 0;i<nl.getLength();i++){ 
    //lets create our HASHMAP!! (feeds items into our ArrayList) 
    HashMap<String, String> map = new HashMap<String, String>(); 
    Element e = (Element) nl.item(i); 
    //add each child node to the HashMap (key, value/<String, String>) 
    map.put(Name, parser.getValue(e, Name)); 
    map.put(Desc, parser.getValue(e, Desc)); 
    map.put(Link, parser.getValue(e, Link)); 


    menuItems.add(map); 

}//DONE 


ListAdapter adapter = new SimpleAdapter(this, menuItems, R.layout.list_item, 
     new String[] {Name, Desc, Link}, new int []{R.id.name, R.id.description, R.id.link}); 

setListAdapter(adapter); 
     } 
} 

e il gestore:

public class xmlparser{ 

public String getXmlFromUrl(String url) { 
String xml = null; 

try { 

    DefaultHttpClient httpClient = new DefaultHttpClient(); 
    HttpPost httpPost = new HttpPost(url); 

    HttpResponse httpResponse = httpClient.execute(httpPost); 
    HttpEntity httpEntity = httpResponse.getEntity(); 
    xml = EntityUtils.toString(httpEntity); 

} catch (UnsupportedEncodingException e) { 
    e.printStackTrace(); 
} catch (ClientProtocolException e) { 
    e.printStackTrace(); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

return xml; 
} 
public Document getDomElement(String xml){ 
    Document doc = null; 
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    try { 

     DocumentBuilder db = dbf.newDocumentBuilder(); 

     InputSource is = new InputSource(); 
      is.setCharacterStream(new StringReader(xml)); 
      doc = db.parse(is); 

     } catch (ParserConfigurationException e) { 
      Log.e("Error: ", e.getMessage()); 
      return null; 
     } catch (SAXException e) { 
      Log.e("Error: ", e.getMessage()); 
      return null; 
     } catch (IOException e) { 
      Log.e("Error: ", e.getMessage()); 
      return null; 
     } 

     return doc; 
    } 

public String getValue(Element item, String str) {  
     NodeList n = item.getElementsByTagName(str);   
     return this.getElementValue(n.item(0)); 
    } 

public final String getElementValue(Node elem) { 
     Node child; 
     if(elem != null){ 
      if (elem.hasChildNodes()){ 
       for(child = elem.getFirstChild(); child != null; child = child.getNextSibling()){ 
        if(child.getNodeType() == Node.TEXT_NODE ){ 
         return child.getNodeValue(); 
        } 
       } 
      } 
     } 
     return ""; 
    }  

}

Qualsiasi idea del perché? Dovrebbe funzionare, tutte le esercitazioni che ho letto trattano questo come codice funzionante ma non viene eseguito e lancia solo l'eccezione. Ho letto che potrei aver bisogno di implementare asynctask ma non sono nuovo ad esso e non sono sicuro di quali parti hanno bisogno del loro thread. Grazie per qualsiasi aiuto, critica (costruttiva), suggerimenti, ecc.

+0

possibile duplicato del [android.os.NetworkOnMainThreadException] (http://stackoverflow.com/questions/6343166/android-os-networkonmainthreadexception) –

risposta

10

Qualche idea sul perché?

Perché se quel pezzo di codice viene eseguito sul thread dell'applicazione principale, si esegue l'I/O di rete sul thread dell'applicazione principale.

Ho letto che potrebbe essere necessario implementare asynctask ma non sono nuovo ad esso e non sono sicuro di quali parti hanno bisogno del proprio thread.

avrei messo la rete di I/O e l'analisi in doInBackground() e setListAdapter() chiamata in onPostExecute() di un AsyncTask.

+0

Grazie che ha aiutato molto, sta funzionando ora :) – Bob

+0

E per chiunque sia interessato ecco il codice funzionante: – Bob

+1

dov'è il codice? – auraham

1

Aggiunta alla risposta CommonsWare, NetworkOnMainThreadException è stata aggiunta a volte tra 2.3.3 (Gingerbread_MR1) e 3.0 (Honeycomb). Se si guarda alla

android.app.ActivityThread 

troverete il seguente pezzo di codice:

/** 
    * For apps targetting SDK Honeycomb or later, we don't allow 
    * network usage on the main event loop/UI thread. 
    * 
    * Note to those grepping: this is what ultimately throws 
    * NetworkOnMainThreadException ... 
    */ 
    if (data.appInfo.targetSdkVersion > 9) { 
     StrictMode.enableDeathOnNetwork(); 
    } 

Credo che i tutorial che si stavano Erano scritto prima di questo è stato messo in atto, e quindi non ha causato il NetworkOnMainThreadException. Segui le istruzioni di CommonsWare riguardanti AsyncTask e correggerai il tuo errore.

+0

Grazie per il piacere di sapere :) – Bob

3

Se si vuole semplicemente testare il codice, e non voglio aggiungere ancora più complicazioni, è possibile aggiungere questo al vostro onCreate()

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

Non si vuole che questo sia permanente, come le operazioni di rete sul thread dell'interfaccia utente creano un'esperienza negativa durante l'utilizzo dell'app, ma possono essere utili durante il test.